odoo18/addons_extensions/hr_attendance_extended/models/hr_attendance.py

114 lines
5.6 KiB
Python

from odoo import fields, api, models
from datetime import datetime
class AttendanceAttendance(models.Model):
_name = "attendance.attendance"
date = fields.Date(string='Date', default=fields.Date.today, required=True)
work_location_id = fields.Many2one('hr.work.location', default=lambda self: self.env.company.id)
attendance_data = fields.One2many('attendance.data','attendance_id', string="Attendance Data")
_sql_constraints = [
('name_date_work_location_id_unique', 'unique(date, work_location_id)', 'The combination of date and work_location_id should be unique.')
]
def get_attendance_for_date(self, rec_date, employee_id):
# Convert rec.date to a datetime object for filtering
start_of_day = fields.Datetime.to_string(
fields.Datetime.from_string(rec_date).replace(hour=0, minute=0, second=0))
end_of_day = fields.Datetime.to_string(
fields.Datetime.from_string(rec_date).replace(hour=23, minute=59, second=59))
# Filter attendance records for the given employee and date range
attendance_records = self.env['hr.attendance'].sudo().search([
('employee_id', '=', employee_id),
('check_in', '>=', start_of_day),
('check_in', '<=', end_of_day)
],order='check_in asc')
if not attendance_records:
return False, False, False
# Initialize variables to track min check_in and max check_out
min_check_in = None
max_check_out = None
for record in attendance_records:
if min_check_in is None or record.check_in < min_check_in:
min_check_in = record.check_in
if max_check_out is None or (record.check_out and record.check_out > max_check_out):
max_check_out = record.check_out
# If no check_out found, set max_check_out to current time
if not max_check_out:
max_check_out = False
total_worked_hours = sum(record.worked_hours for record in attendance_records)
# Return the min_check_in and max_check_out
return min_check_in, max_check_out, total_worked_hours
def update_attendance_data(self):
for rec in self:
if rec.date and rec.work_location_id:
rec.attendance_data.unlink()
emp_work_location_history = self.env['emp.work.location.history'].sudo().search([('employee_id.company_id','=',self.env.company.id),('employee_id.work_location_id','=',rec.work_location_id.id),('start_date','<=',rec.date),'|',('end_date','=',False),('end_date','>=',rec.date)]).employee_id.ids
employees = self.env['hr.employee'].sudo().search([('id','not in',emp_work_location_history),('work_location_id','=',rec.work_location_id.id)]).ids
all_employees = self.env['hr.employee'].sudo().search([('id','in',list(set(emp_work_location_history) | set(employees)))])
attendance_data = list()
for emp in all_employees:
leaves = self.env['hr.leave'].search([('employee_id','=',emp.id),('request_date_from', '<=', rec.date),('request_date_to', '>=', rec.date),('state','=','validate')])
check_in, check_out, worked_hours = self.get_attendance_for_date(rec.date,emp.id)
if leaves:
status = 'leave'
elif check_in or check_out:
status = 'present'
else:
status = 'no_info'
if not leaves and (check_in and check_out):
# Calculate total hours between check_in and check_out in float format
total_hours = (check_out - check_in).total_seconds() / 3600 # Convert seconds to hours
# Calculate out_time as the difference between total_hours and worked_hours
out_time = total_hours - (worked_hours if worked_hours else 0)
else:
total_hours = 0
out_time = 0
data = self.env['attendance.data'].sudo().create({
'employee_id': emp.id,
'min_check_in': check_in if check_in else False,
'max_check_out': check_out if check_out else False,
'worked_hours': worked_hours if worked_hours else False,
'out_time': out_time if out_time else False,
'status': status,
'attendance_id': rec.id
})
attendance_data.append(data.id)
rec.attendance_data = [(6, 0, attendance_data)]
def update_hr_attendance_check_out(self):
attendance = self.env['hr.attendance'].sudo().search([('check_in','!=', False),('check_out','=',False)])
for rec in attendance:
rec.check_out = fields.Datetime.to_string(
fields.Datetime.from_string(rec.check_in).replace(hour=21, minute=0, second=59))
class AttendanceData(models.Model):
_name = 'attendance.data'
employee_id = fields.Many2one('hr.employee')
min_check_in = fields.Datetime(string="Check In")
max_check_out = fields.Datetime(string="Check Out")
out_time = fields.Float()
worked_hours = fields.Float()
# extra_hours = fields.Float()
status = fields.Selection([('leave','On Leave'),('present','Present'),('no_info','No Information')])
attendance_id = fields.Many2one('attendance.attendance')
class HRAttendnace(models.Model):
_inherit = 'hr.attendance'
employee_id = fields.Many2one(group_expand='')