This commit is contained in:
李鹏宇
2026-02-07 12:01:01 +08:00
@@ -648,13 +648,10 @@ class YuthonVacationReports(models.Model):
is_early = 0
is_no = 0
is_work = 0
leave_days = 0
test_days = 0
statutory_days = 0
is_abnormal = 0
right_days = 0
actual_attendance = 0 # 实到天数 = 应到天数 - 请假总天数 - 异常天数 + 法定节假日
total_leave_days = 0 # 请假工作流总天数(含小时折算)
probation_days = 0 # 试用期天数
regular_days = 0 # 转正天数
actual_attendance = 0 # 实到天数 = 应到天数 - 请假总天数 - 异常天数
is_retired = rec.employee_id.user_state in ('leave', 'withdraw')
if rec.employee_id and rec.vacation_date and not is_retired:
year = rec.vacation_date.year
@@ -677,8 +674,10 @@ class YuthonVacationReports(models.Model):
if attendances:
valid_attendances = [
att for att in attendances
if (att.check_in or att.check_out) # 有有效打卡
if (att.check_in or att.check_out)
and att.shift_name != '休息'
and (not att.workflow_id or att.workflow_id.workflow_id.name != '请假')
and not att.is_abnormal
]
if valid_attendances:
actual_attendance += 1
@@ -695,21 +694,6 @@ class YuthonVacationReports(models.Model):
if att.is_abnormal:
is_abnormal += 1
for att in attendances:
if att.workflow_id and att.workflow_id.workflow_id.name == '请假':
res_model = att.workflow_id.res_model
res_id = att.workflow_id.res_id
if res_model and res_id:
related_model = self.env[res_model].sudo().browse(res_id)
if related_model.exists():
if related_model.days:
total_leave_days += float(related_model.days)
# 小时数折算为天数(1天=8小时)
elif related_model.hours:
total_leave_days += float(related_model.hours) / 8
actual_attendance = actual_attendance - total_leave_days - is_abnormal
employee = rec.employee_id
contract = employee.contract_id
is_outside = employee.user_role_id.name == '外派'
@@ -722,32 +706,34 @@ class YuthonVacationReports(models.Model):
start_date = month_start
# 计算end_date:外派且无合同时用month_end;有合同且有结束日则取最小值;其他情况用month_end
end_date = month_end if (is_outside and not contract) else (min(contract.date_end, month_end) if contract.date_end else month_end)
leave_days, statutory_days = rec._create_leave_record(rec.employee_id, start_date, end_date)
work_days = rec._create_leave_record(rec.employee_id, start_date, end_date)
probation_contract = self.env['hr.contract'].search([
('employee_id', '=', rec.employee_id.id),
('is_probation', '=', True),
('end_date', '>=', month_start),
], limit=1)
if probation_contract:
end_date = min(probation_contract.end_date, month_end)
start_date = max(probation_contract.start_date, month_start)
work_days, statutory_days = rec._create_leave_record(rec.employee_id, start_date, end_date)
test_days = work_days + statutory_days
right_days = (leave_days + statutory_days) - (work_days + statutory_days)
else:
test_days = 0
right_days = 0
prob_end = min(probation_contract.end_date, month_end)
prob_start = max(probation_contract.start_date, month_start)
if prob_start <= prob_end: # 避免开始日期大于结束日期
probation_days = rec._create_leave_record(rec.employee_id, prob_start, prob_end)
rec.should_attendance = leave_days + statutory_days
rec.test_days = test_days
rec.right_days = right_days
rec.is_late_card = is_late
rec.is_early_card = is_early
rec.is_no_card = is_no
rec.is_work = is_work
rec.is_abnormal = is_abnormal
rec.actual_attendance = max(actual_attendance + statutory_days, 0)
rec.att_mount = actual_attendance
# 转正阶段的时间范围:当月剩余时段(实习结束后 → 月末)
reg_start = prob_end + timedelta(days=1)
reg_end = month_end
if reg_start <= reg_end:
regular_days = rec._create_leave_record(rec.employee_id, reg_start, reg_end)
rec.should_attendance = work_days
rec.test_days = probation_days
rec.right_days = regular_days
rec.is_late_card = is_late
rec.is_early_card = is_early
rec.is_no_card = is_no
rec.is_work = is_work
rec.is_abnormal = is_abnormal
rec.actual_attendance = actual_attendance
rec.att_mount = actual_attendance
def update_is_confirm1(self):
records = self.env["yuthon.vacation.reports"].browse(
@@ -857,8 +843,9 @@ class YuthonVacationReports(models.Model):
def _create_leave_record(self, employee_id, start_date, end_date):
entry_date = employee_id.entry_date
# 调整日期范围:如果开始日期早于入职日期,则从入职日期开始计算
actual_start_date = max(start_date, entry_date) if entry_date else start_date
if actual_start_date > end_date:
return 0
current_year = (fields.Date.today() + timedelta(hours=8)).year
query_start = datetime(current_year, 1, 1, 0, 0, 0) - timedelta(hours=8)
query_end = datetime(current_year, 12, 31, 23, 59, 59) - timedelta(hours=8)
@@ -867,43 +854,37 @@ class YuthonVacationReports(models.Model):
("date_from", ">=", query_start),
("date_from", "<=", query_end)
])
holidays_list = [] # 节假日列表
statutory_list = [] # 法定节假日列表
shift_days_list = [] # 调休日列表
# 提取节假日和调休日
exclude_days = set()
include_shift_days = set()
for leave in calendar_leaves:
# 法定节假日
if leave.holidays:
holidays_list.extend(leave.holidays.split(','))
statutory_list.extend(leave.holidays.split(','))
exclude_days.update([self.remove_leading_zero(d) for d in leave.holidays.split(',')])
# 调休休息日
if leave.alternate_rest_day:
holidays_list.extend(leave.alternate_rest_day.split(','))
exclude_days.update([self.remove_leading_zero(d) for d in leave.alternate_rest_day.split(',')])
# 调班日
if leave.shift_replacement_day:
shift_days_list.extend(leave.shift_replacement_day.split(','))
include_shift_days.update([self.remove_leading_zero(d) for d in leave.shift_replacement_day.split(',')])
# 去除日期中的前导零(如"01月05日"→"1月5日")
holidays_list = [self.remove_leading_zero(date) for date in holidays_list]
shift_days_list = [self.remove_leading_zero(date) for date in shift_days_list]
statutory_list = [self.remove_leading_zero(date) for date in statutory_list]
work_days = 0 # 工作日计数
statutory_days = 0 # 法定节假日计数
total_days = 0
current_date = actual_start_date
while current_date <= end_date:
current_date_str = current_date.strftime('%m月%d日')
current_date_str = self.remove_leading_zero(current_date_str)
current_date_str = self.remove_leading_zero(current_date.strftime('%m月%d日'))
is_weekend = current_date.weekday() in [5, 6]
is_statutory = current_date_str in statutory_list
is_holiday = current_date_str in holidays_list
is_shift_day = current_date_str in shift_days_list
if is_shift_day or (not is_weekend and not is_holiday):
work_days += 1
if is_statutory:
statutory_days += 1
is_exclude = current_date_str in exclude_days
is_shift_day = current_date_str in include_shift_days
if not is_exclude:
if not is_weekend:
total_days += 1
elif is_shift_day:
total_days += 1
current_date += timedelta(days=1)
return work_days, statutory_days
return total_days
def remove_leading_zero(self, date_str):
month, day = date_str.split('月')