Merge pull request #5433 from expsa/kch_dev_odex25_hr

[FIX] attendances: fix bug
This commit is contained in:
kchyounes19 2025-11-16 13:21:20 +01:00 committed by GitHub
commit ea38d1cc08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 149 additions and 33 deletions

View File

@ -65,59 +65,168 @@ class HrAttendanceTransactions(models.Model):
rec.additional_hours = rec.office_hours - rec.plan_hours
# rec.carried_hours = rec.office_hours - rec.plan_hours
# def get_shift_timings(self, item):
# calendar = item.calendar_id
# if calendar.is_full_day:
# min_sign_in = calendar.full_min_sign_in
# full_max_sign_in = calendar.full_max_sign_in
# max_sign_out = calendar.full_max_sign_out
# working_hours = calendar.working_hours
# else:
# if item.sequence == 1:
# min_sign_in = calendar.shift_one_min_sign_in
# full_max_sign_in = calendar.shift_one_max_sign_in
# max_sign_out = calendar.shift_one_max_sign_out
# working_hours = calendar.shift_one_working_hours
# elif item.sequence == 2:
# min_sign_in = calendar.shift_two_min_sign_in
# full_max_sign_in = calendar.shift_two_max_sign_in
# max_sign_out = calendar.shift_two_max_sign_out
# working_hours = calendar.shift_two_working_hours
# else:
# min_sign_in = max_sign_out = working_hours = None # or default fallback
# return min_sign_in, full_max_sign_in , max_sign_out, working_hours
def get_shift_timings(self, item):
calendar = item.calendar_id
date = item.date
weekday = date.strftime('%A').lower() # اسم اليوم مثل 'monday'
# جلب اليوم الخاص إن وجد
sp_days = calendar.special_days_partcial if not calendar.is_full_day else calendar.special_days
sp_timing = None
for sp in sp_days:
# تحقق من اليوم ونوع الشفت إن وجد
if sp.name.lower() == weekday and (
(calendar.is_full_day and not sp.shift) or
(not calendar.is_full_day and sp.shift == ('one' if item.sequence == 1 else 'two'))
):
if sp.date_from and sp.date_to and str(date) >= sp.date_from and str(date) <= sp.date_to:
sp_timing = sp
break
elif sp.date_from and not sp.date_to and str(date) >= sp.date_from:
sp_timing = sp
break
elif not sp.date_from and sp.date_to and str(date) <= sp.date_to:
sp_timing = sp
break
elif not sp.date_from and not sp.date_to:
sp_timing = sp
break
# الآن نحسب التوقيتات بناءً على نوع الجدول وفترة العمل
if calendar.is_full_day:
min_sign_in = calendar.full_min_sign_in
full_max_sign_in = calendar.full_max_sign_in
max_sign_out = calendar.full_max_sign_out
working_hours = calendar.working_hours
min_sign_in = sp_timing.start_sign_in if sp_timing else calendar.full_min_sign_in
full_max_sign_in = sp_timing.end_sign_in if sp_timing else calendar.full_max_sign_in
max_sign_out = sp_timing.end_sign_out if sp_timing else calendar.full_max_sign_out
working_hours = (sp_timing.working_hours if sp_timing else calendar.working_hours) - calendar.break_duration
else:
if item.sequence == 1:
min_sign_in = calendar.shift_one_min_sign_in
full_max_sign_in = calendar.shift_one_max_sign_in
max_sign_out = calendar.shift_one_max_sign_out
working_hours = calendar.shift_one_working_hours
min_sign_in = sp_timing.start_sign_in if sp_timing else calendar.shift_one_min_sign_in
full_max_sign_in = sp_timing.end_sign_in if sp_timing else calendar.shift_one_max_sign_in
max_sign_out = sp_timing.end_sign_out if sp_timing else calendar.shift_one_max_sign_out
working_hours = (sp_timing.working_hours if sp_timing else calendar.shift_one_working_hours) - calendar.shift_one_break_duration
elif item.sequence == 2:
min_sign_in = calendar.shift_two_min_sign_in
full_max_sign_in = calendar.shift_two_max_sign_in
max_sign_out = calendar.shift_two_max_sign_out
working_hours = calendar.shift_two_working_hours
min_sign_in = sp_timing.start_sign_in if sp_timing else calendar.shift_two_min_sign_in
full_max_sign_in = sp_timing.end_sign_in if sp_timing else calendar.shift_two_max_sign_in
max_sign_out = sp_timing.end_sign_out if sp_timing else calendar.shift_two_max_sign_out
working_hours = (sp_timing.working_hours if sp_timing else calendar.shift_two_working_hours) - calendar.shift_two_break_duration
else:
min_sign_in = max_sign_out = working_hours = None # or default fallback
min_sign_in = full_max_sign_in = max_sign_out = working_hours = None
return min_sign_in, full_max_sign_in , max_sign_out, working_hours
return min_sign_in, full_max_sign_in, max_sign_out, working_hours
def _compute_expected_times(self, item):
"""Helper function to compute expected sign-in and sign-out times based on calendar settings."""
expected_sign_in = 0
expected_sign_out = 0
"""Compute expected sign-in and sign-out times considering calendar and special days."""
calendar = item.calendar_id
date = item.date
weekday = date.strftime('%A').lower()
full_max_sign_in = item.calendar_id.full_max_sign_in
full_min_sign_in = item.calendar_id.full_min_sign_in
working_hours = item.calendar_id.working_hours
# اختيار قائمة الأيام الخاصة بناءً على نوع الدوام
sp_days = calendar.special_days_partcial if not calendar.is_full_day else calendar.special_days
sp_timing = None
if not item.calendar_id.is_full_day:
# البحث عن يوم خاص يطابق اليوم الحالي والفترة
for sp in sp_days:
if sp.name.lower() == weekday and (
(calendar.is_full_day and not sp.shift) or
(not calendar.is_full_day and sp.shift == ('one' if item.sequence == 1 else 'two'))
):
if sp.date_from and sp.date_to and str(date) >= sp.date_from and str(date) <= sp.date_to:
sp_timing = sp
break
elif sp.date_from and not sp.date_to and str(date) >= sp.date_from:
sp_timing = sp
break
elif not sp.date_from and sp.date_to and str(date) <= sp.date_to:
sp_timing = sp
break
elif not sp.date_from and not sp.date_to:
sp_timing = sp
break
# تعيين التوقيتات حسب وجود يوم خاص أو لا
if calendar.is_full_day:
full_min_sign_in = sp_timing.start_sign_in if sp_timing else calendar.full_min_sign_in
full_max_sign_in = sp_timing.end_sign_in if sp_timing else calendar.full_max_sign_in
working_hours = sp_timing.working_hours if sp_timing else calendar.working_hours
else:
if item.sequence == 1:
full_max_sign_in = item.calendar_id.shift_one_max_sign_in
full_min_sign_in = item.calendar_id.shift_one_min_sign_in
working_hours = item.calendar_id.shift_one_working_hours
full_min_sign_in = sp_timing.start_sign_in if sp_timing else calendar.shift_one_min_sign_in
full_max_sign_in = sp_timing.end_sign_in if sp_timing else calendar.shift_one_max_sign_in
working_hours = sp_timing.working_hours if sp_timing else calendar.shift_one_working_hours
elif item.sequence == 2:
full_max_sign_in = item.calendar_id.shift_two_max_sign_in
full_min_sign_in = item.calendar_id.shift_two_min_sign_in
working_hours = item.calendar_id.shift_two_working_hours
full_min_sign_in = sp_timing.start_sign_in if sp_timing else calendar.shift_two_min_sign_in
full_max_sign_in = sp_timing.end_sign_in if sp_timing else calendar.shift_two_max_sign_in
working_hours = sp_timing.working_hours if sp_timing else calendar.shift_two_working_hours
else:
# fallback default
return 0, 0
# حساب توقيت الدخول المتوقع
if item.sign_in < full_min_sign_in:
expected_sign_in = full_min_sign_in
elif full_min_sign_in <= item.sign_in <= full_max_sign_in:
expected_sign_in = item.sign_in
elif item.sign_in > full_max_sign_in:
else:
expected_sign_in = full_max_sign_in
# توقيت الخروج المتوقع = الدخول + عدد الساعات
expected_sign_out = expected_sign_in + working_hours
return expected_sign_in, expected_sign_out
# def _compute_expected_times(self, item):
# """Helper function to compute expected sign-in and sign-out times based on calendar settings."""
# expected_sign_in = 0
# expected_sign_out = 0
# full_max_sign_in = item.calendar_id.full_max_sign_in
# full_min_sign_in = item.calendar_id.full_min_sign_in
# working_hours = item.calendar_id.working_hours
# if not item.calendar_id.is_full_day:
# if item.sequence == 1:
# full_max_sign_in = item.calendar_id.shift_one_max_sign_in
# full_min_sign_in = item.calendar_id.shift_one_min_sign_in
# working_hours = item.calendar_id.shift_one_working_hours
# elif item.sequence == 2:
# full_max_sign_in = item.calendar_id.shift_two_max_sign_in
# full_min_sign_in = item.calendar_id.shift_two_min_sign_in
# working_hours = item.calendar_id.shift_two_working_hours
# if item.sign_in < full_min_sign_in:
# expected_sign_in = full_min_sign_in
# elif full_min_sign_in <= item.sign_in <= full_max_sign_in:
# expected_sign_in = item.sign_in
# elif item.sign_in > full_max_sign_in:
# expected_sign_in = full_max_sign_in
# expected_sign_out = expected_sign_in + working_hours
# return expected_sign_in, expected_sign_out
def set_lateness_and_exit(self, item , expected_sign_in=None , expected_sign_out=None):
if not expected_sign_in and not expected_sign_out:
expected_sign_in, expected_sign_out = self._compute_expected_times(item)
@ -173,6 +282,8 @@ class HrAttendanceTransactions(models.Model):
def _calculate_working_hours(self, day_trans):
""" Helper method to calculate total working hours """
print({'office_hours': sum(day_trans.mapped('office_hours')) + sum(day_trans.mapped('total_mission_hours'))})
print(sum(day_trans.mapped('office_hours')) , sum(day_trans.mapped('total_mission_hours')))
day_trans.update({'office_hours': sum(day_trans.mapped('office_hours')) + sum(day_trans.mapped('total_mission_hours'))})
return (
sum(day_trans.mapped('office_hours')) + sum(day_trans.mapped('total_permission_hours'))
@ -436,11 +547,11 @@ class HrAttendanceTransactions(models.Model):
for spday in sp_days:
if spday.name.lower() == weekday and ((shift and spday.shift == shift) or (not shift and True)):
if spday.date_from and spday.date_to \
and at_date >= spday.date_from and at_date <= spday.date_to:
and str(at_date) >= spday.date_from and str(at_date) <= spday.date_to:
return spday
elif spday.date_from and not spday.date_to and at_date >= spday.date_from:
elif spday.date_from and not spday.date_to and str(at_date) >= spday.date_from:
return spday
elif not spday.date_from and spday.date_to and at_date <= spday.date_to:
elif not spday.date_from and spday.date_to and str(at_date) <= spday.date_to:
return spday
elif not spday.date_from and not spday.date_to:
return spday
@ -651,7 +762,7 @@ class HrAttendanceTransactions(models.Model):
return {'shift': shift_dict, 'out_ids': linked_out_ids, 'creep': creep}
def manage_permission(self, trans_id, shift_in, shift_out, sign_in, sign_out, breaks, state=None):
#print(trans_id, "*********************manage_permission***********************************")
print(trans_id, "*********************manage_permission***********************************")
trans, feedback = self.browse(trans_id)[0], []
# حساب التوقيع المتوقع للدخول والخروج بناء علي بصمة الدخول
expected_sign_in, expected_sign_out = self._compute_expected_times(trans)
@ -796,7 +907,7 @@ class HrAttendanceTransactions(models.Model):
if state is not None: return feedback
def manage_mission(self, trans_id, shift_in, shift_out, sign_in, sign_out, breaks, state=None):
#print(trans_id, "*********************manage_mission***********************************")
print(trans_id, "*********************manage_mission***********************************")
trans , feedback = self.browse(trans_id)[0] , []
expected_sign_in, expected_sign_out = self._compute_expected_times(trans)
full_min_sign_in, full_max_sign_in, full_max_sign_out, working_hours = self.get_shift_timings(trans)
@ -839,6 +950,11 @@ class HrAttendanceTransactions(models.Model):
continue
elif trans.sign_in == 0.0 or trans.sign_out == 0.0:
mission_hours = min(trans.plan_hours, emp_mission.hours)
print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
print(mission_hours)
print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
miss_dic = {'is_official': True, 'official_id': mission.id, 'total_mission_hours': mission_hours, }
if state != 'check':trans.update(miss_dic)
if state is not None:feedback.append({'mission_id': mission.id, 'miss_start': mission_df, 'miss_end': mission_dt, 'type': 'all'})