oca-ocb-hr/odoo-bringout-oca-ocb-hr/hr/models/hr_employee_public.py
Ernad Husremovic e1d89e11e3 19.0 vanilla
2026-03-09 09:31:00 +01:00

205 lines
9.6 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import timedelta
from pytz import timezone, UTC
from odoo import api, fields, models, tools
from odoo.tools import format_time
class HrEmployeePublic(models.Model):
_name = 'hr.employee.public'
_description = 'Public Employee'
_order = 'name'
_auto = False
_log_access = True # Include magic fields
# Fields coming from hr.employee
create_date = fields.Datetime(readonly=True)
name = fields.Char(readonly=True)
active = fields.Boolean(readonly=True)
department_id = fields.Many2one('hr.department', readonly=True)
member_of_department = fields.Boolean(compute='_compute_member_of_department', search='_search_part_of_department')
job_id = fields.Many2one('hr.job', readonly=True)
job_title = fields.Char(related='employee_id.job_title')
company_id = fields.Many2one('res.company', readonly=True)
address_id = fields.Many2one('res.partner', readonly=True)
mobile_phone = fields.Char(readonly=True)
work_phone = fields.Char(readonly=True)
work_email = fields.Char(readonly=True)
share = fields.Boolean(related='employee_id.share')
phone = fields.Char(related='employee_id.phone')
im_status = fields.Char(related='employee_id.im_status')
email = fields.Char(related='employee_id.email')
work_contact_id = fields.Many2one('res.partner', readonly=True)
work_location_id = fields.Many2one('hr.work.location', readonly=True)
work_location_name = fields.Char(related='employee_id.work_location_name')
work_location_type = fields.Selection(related='employee_id.work_location_type')
user_id = fields.Many2one('res.users', readonly=True)
resource_id = fields.Many2one('resource.resource', readonly=True)
tz = fields.Selection(related='resource_id.tz')
color = fields.Integer(readonly=True)
hr_presence_state = fields.Selection([
('present', 'Present'),
('absent', 'Absent'),
('archive', 'Archived'),
('out_of_working_hour', 'Off-Hours')], compute='_compute_presence_state', default='out_of_working_hour')
hr_icon_display = fields.Selection(
selection='_get_selection_hr_icon_display',
compute='_compute_presence_icon')
show_hr_icon_display = fields.Boolean(compute='_compute_presence_icon')
last_activity = fields.Date(compute="_compute_last_activity")
last_activity_time = fields.Char(compute="_compute_last_activity")
resource_calendar_id = fields.Many2one('resource.calendar', readonly=True)
country_code = fields.Char(compute='_compute_country_code')
# Manager-only fields
is_manager = fields.Boolean(compute='_compute_is_manager')
is_user = fields.Boolean(compute='_compute_is_user')
employee_id = fields.Many2one('hr.employee', 'Employee', readonly=True)
# hr.employee.public specific fields
child_ids = fields.One2many('hr.employee.public', 'parent_id', string='Direct subordinates', readonly=True)
image_1920 = fields.Image("Image", related='employee_id.image_1920', compute_sudo=True)
image_1024 = fields.Image("Image 1024", related='employee_id.image_1024', compute_sudo=True)
image_512 = fields.Image("Image 512", related='employee_id.image_512', compute_sudo=True)
image_256 = fields.Image("Image 256", related='employee_id.image_256', compute_sudo=True)
image_128 = fields.Image("Image 128", related='employee_id.image_128', compute_sudo=True)
avatar_1920 = fields.Image("Avatar", related='employee_id.avatar_1920', compute_sudo=True)
avatar_1024 = fields.Image("Avatar 1024", related='employee_id.avatar_1024', compute_sudo=True)
avatar_512 = fields.Image("Avatar 512", related='employee_id.avatar_512', compute_sudo=True)
avatar_256 = fields.Image("Avatar 256", related='employee_id.avatar_256', compute_sudo=True)
avatar_128 = fields.Image("Avatar 128", related='employee_id.avatar_128', compute_sudo=True)
parent_id = fields.Many2one('hr.employee.public', 'Manager', readonly=True)
coach_id = fields.Many2one('hr.employee.public', 'Coach', readonly=True)
user_partner_id = fields.Many2one(related='user_id.partner_id', related_sudo=False, string="User's partner")
birthday_public_display_string = fields.Char("Public Date of Birth", related='employee_id.birthday_public_display_string')
newly_hired = fields.Boolean('Newly Hired', compute='_compute_newly_hired', search='_search_newly_hired')
def _get_selection_hr_icon_display(self):
return self.env['hr.employee']._fields['hr_icon_display']._description_selection(self.env)
def _compute_from_employee(self, field_names):
if isinstance(field_names, str):
field_names = [field_names]
employees_sudo = self.sudo().env['hr.employee'].browse(self.ids)
employee_per_id = {emp.id: emp for emp in employees_sudo}
for public_employee in self:
employee = employee_per_id[public_employee.id]
for field_name in field_names:
public_employee[field_name] = employee[field_name]
@api.depends('user_id')
def _compute_last_activity(self):
for employee in self:
tz = employee.tz
# sudo: res.users - can access presence of accessible user
if last_presence := employee.user_id.sudo().presence_ids.last_presence:
last_activity_datetime = last_presence.replace(tzinfo=UTC).astimezone(timezone(tz)).replace(tzinfo=None)
employee.last_activity = last_activity_datetime.date()
if employee.last_activity == fields.Date.today():
employee.last_activity_time = format_time(self.env, last_presence, time_format='short')
else:
employee.last_activity_time = False
else:
employee.last_activity = False
employee.last_activity_time = False
def _compute_country_code(self):
self._compute_from_employee('country_code')
@api.depends_context('uid')
@api.depends('parent_id')
def _compute_is_manager(self):
all_reports = self.env['hr.employee.public'].search([('id', 'child_of', self.env.user.employee_id.id)]).ids
for employee in self:
employee.is_manager = employee.id in all_reports
@api.depends_context('uid')
def _compute_is_user(self):
user_employee_id = self.env.user.employee_id.id
for employee in self:
employee.is_user = employee.id == user_employee_id
def _compute_presence_state(self):
self._compute_from_employee('hr_presence_state')
def _compute_presence_icon(self):
self._compute_from_employee('hr_icon_display')
self._compute_from_employee('show_hr_icon_display')
def _compute_member_of_department(self):
self._compute_from_employee('member_of_department')
def _get_manager_only_fields(self):
return []
def _search_part_of_department(self, operator, value):
if operator != 'in':
return NotImplemented
user_employee = self._get_valid_employee_for_user()
if not user_employee.department_id:
return [('id', 'in', user_employee.ids)]
return [('department_id', 'child_of', user_employee.department_id.ids)]
def _get_valid_employee_for_user(self):
user = self.env.user
# retrieve the employee of the current active company for the user
employee = user.employee_id
if not employee:
# search for all employees as superadmin to not get blocked by multi-company rules
user_employees = user.employee_id.sudo().search([
('user_id', '=', user.id)
])
# the default company employee is most likely the correct one, but fallback to the first if not available
employee = user_employees.filtered(lambda r: r.company_id == user.company_id) or user_employees[:1]
return employee
@api.depends_context('uid')
def _compute_manager_only_fields(self):
manager_fields = self._get_manager_only_fields()
for employee in self:
if employee.is_manager:
employee_sudo = employee.employee_id.sudo()
for f in manager_fields:
employee[f] = employee_sudo[f]
else:
for f in manager_fields:
employee[f] = False
def _compute_newly_hired(self):
self._compute_from_employee('newly_hired')
def _search_newly_hired(self, operator, value):
if operator not in ('in', 'not in'):
return NotImplemented
new_hire_field = self.env['hr.employee']._get_new_hire_field()
new_hires = self.env['hr.employee'].sudo().search([
(new_hire_field, '>', fields.Datetime.now() - timedelta(days=90))
])
return [('id', operator, new_hires.ids)]
@api.model
def _get_fields(self):
base_fields = ('id', 'employee_id', 'name', 'active')
version_fields = self.env['hr.version']._fields
return 'e.id AS id,e.id AS employee_id,e.name AS name,e.active AS active,' + ','.join(
(f'v.{name}' if name in version_fields and version_fields[name].store else f'e.{name}')
for name, field in self._fields.items()
if name not in base_fields and field.store and field.column_type
)
def init(self):
tools.drop_view_if_exists(self.env.cr, self._table)
self.env.cr.execute("""CREATE or REPLACE VIEW %s as (
SELECT
%s
FROM hr_employee e
JOIN hr_version v
ON v.id = e.current_version_id
)""" % (self._table, self._get_fields()))
def get_avatar_card_data(self, fields):
return self.read(fields)