114 lines
5.6 KiB
Python
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='')
|