mirror of
https://github.com/bringout/oca-ocb-hr.git
synced 2026-04-26 08:12:04 +02:00
19.0 vanilla
This commit is contained in:
parent
e1d89e11e3
commit
a1f02d8cc7
225 changed files with 2335 additions and 775 deletions
|
|
@ -182,8 +182,8 @@ class HrAttendance(models.Model):
|
|||
calendar = self._get_employee_calendar()
|
||||
resource = self.employee_id.resource_id
|
||||
tz = timezone(resource.tz) if not calendar else timezone(calendar.tz)
|
||||
start_dt_tz = max(self.check_in, start_dt).astimezone(tz)
|
||||
end_dt_tz = min(self.check_out, end_dt).astimezone(tz)
|
||||
start_dt_tz = utc.localize(max(self.check_in, start_dt)).astimezone(tz)
|
||||
end_dt_tz = utc.localize(min(self.check_out, end_dt)).astimezone(tz)
|
||||
|
||||
if end_dt_tz < start_dt_tz:
|
||||
return 0.0
|
||||
|
|
@ -268,11 +268,19 @@ class HrAttendance(models.Model):
|
|||
def _get_overtimes_to_update_domain(self):
|
||||
if not self:
|
||||
return Domain.FALSE
|
||||
domain_list = [Domain.AND([
|
||||
Domain('employee_id', '=', employee.id),
|
||||
Domain('date', '<=', max(attendances.mapped('check_out')).date() + relativedelta(SU)),
|
||||
Domain('date', '>=', min(attendances.mapped('check_in')).date() + relativedelta(MO(-1))),
|
||||
]) for employee, attendances in self.filtered(lambda att: att.check_out).grouped('employee_id').items()]
|
||||
domain_list = []
|
||||
for employee, attendances in self.filtered(lambda att: att.check_out).grouped('employee_id').items():
|
||||
tz = timezone(employee._get_tz())
|
||||
local_check_in = utc.localize(min(attendances.mapped('check_in'))).astimezone(tz)
|
||||
local_check_out = utc.localize(max(attendances.mapped('check_out'))).astimezone(tz)
|
||||
date_from = local_check_in.date() + relativedelta(weekday=MO(-1))
|
||||
date_to = local_check_out.date() + relativedelta(weekday=SU)
|
||||
|
||||
domain_list.append(Domain.AND([
|
||||
Domain('employee_id', '=', employee.id),
|
||||
Domain('date', '<=', date_to),
|
||||
Domain('date', '>=', date_from),
|
||||
]))
|
||||
if not domain_list:
|
||||
return Domain.FALSE
|
||||
return Domain.OR(domain_list) if len(domain_list) > 1 else domain_list[0]
|
||||
|
|
@ -280,7 +288,11 @@ class HrAttendance(models.Model):
|
|||
def _update_overtime(self, attendance_domain=None):
|
||||
if not attendance_domain:
|
||||
attendance_domain = self._get_overtimes_to_update_domain()
|
||||
self.env['hr.attendance.overtime.line'].search(attendance_domain).unlink()
|
||||
all_overtime_lines = self.env['hr.attendance.overtime.line'].search(attendance_domain)
|
||||
manual_overtimes = set(all_overtime_lines.filtered(
|
||||
lambda l: l.manual_duration != l.duration or l.status == 'to_approve'
|
||||
).mapped(lambda l: (l.employee_id.id, l.date)))
|
||||
all_overtime_lines.unlink()
|
||||
all_attendances = (self | self.env['hr.attendance'].search(attendance_domain)).filtered_domain([('check_out', '!=', False)])
|
||||
if not all_attendances:
|
||||
return
|
||||
|
|
@ -305,9 +317,13 @@ class HrAttendance(models.Model):
|
|||
overtime_vals_list = []
|
||||
for ruleset_sudo, ruleset_attendances in attendances_by_ruleset.items():
|
||||
attendances_dates = list(chain(*ruleset_attendances._get_dates().values()))
|
||||
overtime_vals_list.extend(
|
||||
ruleset_sudo.rule_ids._generate_overtime_vals_v2(min(attendances_dates), max(attendances_dates), ruleset_attendances, schedules_intervals_by_employee)
|
||||
)
|
||||
overtime_vals_list.extend([
|
||||
{
|
||||
**val,
|
||||
'status': 'to_approve'
|
||||
} if (val['employee_id'], val['date']) in manual_overtimes else val
|
||||
for val in ruleset_sudo.rule_ids._generate_overtime_vals_v2(min(attendances_dates), max(attendances_dates), ruleset_attendances, schedules_intervals_by_employee)
|
||||
])
|
||||
self.env['hr.attendance.overtime.line'].create(overtime_vals_list)
|
||||
self.env.add_to_compute(self._fields['overtime_hours'], all_attendances)
|
||||
self.env.add_to_compute(self._fields['validated_overtime_hours'], all_attendances)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,10 @@ class HrEmployee(models.Model):
|
|||
def _compute_total_overtime(self):
|
||||
mapped_validated_overtimes = dict(
|
||||
self.env['hr.attendance.overtime.line']._read_group(
|
||||
domain=[('status', '=', 'approved')],
|
||||
domain=[
|
||||
('status', '=', 'approved'),
|
||||
('employee_id', 'in', self.ids),
|
||||
],
|
||||
groupby=['employee_id'],
|
||||
aggregates=['manual_duration:sum']
|
||||
))
|
||||
|
|
@ -96,59 +99,66 @@ class HrEmployee(models.Model):
|
|||
"""
|
||||
now = fields.Datetime.now()
|
||||
now_utc = pytz.utc.localize(now)
|
||||
for employee in self:
|
||||
tz = pytz.timezone(employee.tz or 'UTC')
|
||||
for timezone, employees in self.grouped('tz').items():
|
||||
tz = pytz.timezone(timezone or 'UTC')
|
||||
now_tz = now_utc.astimezone(tz)
|
||||
start_tz = now_tz.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||
start_naive = start_tz.astimezone(pytz.utc).replace(tzinfo=None)
|
||||
end_tz = now_tz
|
||||
end_naive = end_tz.astimezone(pytz.utc).replace(tzinfo=None)
|
||||
|
||||
current_month_attendances = employee.attendance_ids.filtered(
|
||||
lambda att: att.check_in >= start_naive and att.check_out and att.check_out <= end_naive
|
||||
)
|
||||
hours = 0
|
||||
overtime_hours = 0
|
||||
for att in current_month_attendances:
|
||||
hours += att.worked_hours or 0
|
||||
overtime_hours += att.validated_overtime_hours or 0
|
||||
employee.hours_last_month = round(hours, 2)
|
||||
employee.hours_last_month_display = "%g" % employee.hours_last_month
|
||||
# overtime_adjustments = sum(
|
||||
# ot.duration or 0
|
||||
# for ot in employee.overtime_ids.filtered(
|
||||
# lambda ot: ot.date >= start_tz.date() and ot.date <= end_tz.date() and ot.adjustment
|
||||
# )
|
||||
# )
|
||||
employee.hours_last_month_overtime = round(overtime_hours, 2)
|
||||
for employee in employees:
|
||||
current_month_attendances = employee.attendance_ids.filtered(
|
||||
lambda att: att.check_in >= start_naive and att.check_out and att.check_out <= end_naive
|
||||
)
|
||||
hours = 0
|
||||
overtime_hours = 0
|
||||
for att in current_month_attendances:
|
||||
hours += att.worked_hours or 0
|
||||
overtime_hours += att.validated_overtime_hours or 0
|
||||
employee.hours_last_month = round(hours, 2)
|
||||
employee.hours_last_month_display = "%g" % employee.hours_last_month
|
||||
# overtime_adjustments = sum(
|
||||
# ot.duration or 0
|
||||
# for ot in employee.overtime_ids.filtered(
|
||||
# lambda ot: ot.date >= start_tz.date() and ot.date <= end_tz.date() and ot.adjustment
|
||||
# )
|
||||
# )
|
||||
employee.hours_last_month_overtime = round(overtime_hours, 2)
|
||||
|
||||
def _compute_hours_today(self):
|
||||
now = fields.Datetime.now()
|
||||
now_utc = pytz.utc.localize(now)
|
||||
for employee in self:
|
||||
for timezone, employees in self.grouped('tz').items():
|
||||
# start of day in the employee's timezone might be the previous day in utc
|
||||
tz = pytz.timezone(employee.tz)
|
||||
now_tz = now_utc.astimezone(tz)
|
||||
start_tz = now_tz + relativedelta(hour=0, minute=0) # day start in the employee's timezone
|
||||
tz = pytz.timezone(timezone or 'UTC')
|
||||
start_tz = now_utc.astimezone(tz) + relativedelta(hour=0, minute=0) # day start in the employee's timezone
|
||||
start_naive = start_tz.astimezone(pytz.utc).replace(tzinfo=None)
|
||||
|
||||
attendances = self.env['hr.attendance'].search([
|
||||
('employee_id', 'in', employee.ids),
|
||||
('check_in', '<=', now),
|
||||
'|', ('check_out', '>=', start_naive), ('check_out', '=', False),
|
||||
], order='check_in asc')
|
||||
hours_previously_today = 0
|
||||
worked_hours = 0
|
||||
attendance_worked_hours = 0
|
||||
for attendance in attendances:
|
||||
delta = (attendance.check_out or now) - max(attendance.check_in, start_naive)
|
||||
attendance_worked_hours = delta.total_seconds() / 3600.0
|
||||
worked_hours += attendance_worked_hours
|
||||
hours_previously_today += attendance_worked_hours
|
||||
employee.last_attendance_worked_hours = attendance_worked_hours
|
||||
hours_previously_today -= attendance_worked_hours
|
||||
employee.hours_previously_today = hours_previously_today
|
||||
employee.hours_today = worked_hours
|
||||
attendances_by_employee = dict(self.env['hr.attendance']._read_group(
|
||||
[
|
||||
('employee_id', 'in', employees.ids),
|
||||
('check_in', '<=', now),
|
||||
'|', ('check_out', '>=', start_naive), ('check_out', '=', False),
|
||||
],
|
||||
['employee_id'],
|
||||
['id:recordset'],
|
||||
))
|
||||
|
||||
for employee in employees:
|
||||
attendances = attendances_by_employee.get(employee, self.env['hr.attendance'])
|
||||
hours_previously_today = 0
|
||||
worked_hours = 0
|
||||
attendance_worked_hours = 0
|
||||
for attendance in attendances:
|
||||
delta = (attendance.check_out or now) - max(attendance.check_in, start_naive)
|
||||
attendance_worked_hours = delta.total_seconds() / 3600.0
|
||||
worked_hours += attendance_worked_hours
|
||||
hours_previously_today += attendance_worked_hours
|
||||
employee.last_attendance_worked_hours = attendance_worked_hours
|
||||
hours_previously_today -= attendance_worked_hours
|
||||
employee.hours_previously_today = hours_previously_today
|
||||
employee.hours_today = worked_hours
|
||||
|
||||
@api.depends('attendance_ids')
|
||||
def _compute_last_attendance_id(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue