智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

277 lines
9.3 KiB

<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\job\transfer\schedule;
use app\model\staff\Staff;
use app\model\staff\StaffAttendance;
use core\base\BaseJob;
use think\facade\Log;
/**
* 定时处理员工考勤状态任务
* 自动生成考勤记录、处理迟到早退、计算工作时长等
*/
class StaffAttendanceJob extends BaseJob
{
/**
* 执行定时任务
* @param mixed ...$data 任务参数
* @return bool 处理结果
*/
public function doJob(...$data)
{
Log::write('开始执行员工考勤状态处理任务');
try {
$currentDate = date('Y-m-d');
$currentTime = date('H:i:s');
// 处理当日考勤记录生成
$generateResult = $this->generateDailyAttendance($currentDate);
// 处理迟到状态更新
$lateResult = $this->processLateArrivals($currentDate, $currentTime);
// 处理早退状态更新
$earlyResult = $this->processEarlyDepartures($currentDate, $currentTime);
// 处理缺勤状态更新
$absentResult = $this->processAbsences($currentDate);
// 计算工作时长
$workHoursResult = $this->calculateWorkHours($currentDate);
Log::write('员工考勤状态处理任务执行完成', [
'generated_records' => $generateResult['count'],
'late_arrivals' => $lateResult['count'],
'early_departures' => $earlyResult['count'],
'absences' => $absentResult['count'],
'calculated_hours' => $workHoursResult['count']
]);
return true;
} catch (\Exception $e) {
Log::write('员工考勤状态处理任务执行失败:' . $e->getMessage());
throw $e;
}
}
/**
* 生成当日考勤记录
* @param string $date 日期
* @return array 处理结果
*/
protected function generateDailyAttendance($date)
{
// 获取所有在职员工
$activeStaff = Staff::where('status', 1)->select();
$count = 0;
foreach ($activeStaff as $staff) {
// 检查是否已有当日考勤记录
$exists = StaffAttendance::where('staff_id', $staff->id)
->where('attendance_date', $date)
->count();
if ($exists == 0) {
// 创建考勤记录
$attendance = new StaffAttendance();
$attendance->staff_id = $staff->id;
$attendance->attendance_date = $date;
$attendance->status = 'pending'; // 待考勤状态
$attendance->work_schedule_start = '09:00:00'; // 默认上班时间
$attendance->work_schedule_end = '18:00:00'; // 默认下班时间
$attendance->created_at = date('Y-m-d H:i:s');
$attendance->save();
$count++;
Log::write("为员工生成考勤记录:员工ID {$staff->id}, 日期: {$date}");
}
}
return ['count' => $count];
}
/**
* 处理迟到状态
* @param string $date 日期
* @param string $currentTime 当前时间
* @return array 处理结果
*/
protected function processLateArrivals($date, $currentTime)
{
// 查找今日还未签到但已过上班时间的员工
$lateThreshold = '09:30:00'; // 迟到阈值:9:30后算迟到
$lateAttendances = StaffAttendance::where('attendance_date', $date)
->where('check_in_time', null)
->where('work_schedule_start', '<', $currentTime)
->select();
$count = 0;
foreach ($lateAttendances as $attendance) {
if ($currentTime > $lateThreshold) {
$attendance->status = 'late';
$attendance->late_minutes = $this->calculateLateMinutes($attendance->work_schedule_start, $currentTime);
$attendance->save();
$count++;
Log::write("员工迟到:员工ID {$attendance->staff_id}, 迟到 {$attendance->late_minutes} 分钟");
}
}
return ['count' => $count];
}
/**
* 处理早退状态
* @param string $date 日期
* @param string $currentTime 当前时间
* @return array 处理结果
*/
protected function processEarlyDepartures($date, $currentTime)
{
// 查找今日已签到但提前签退的员工
$earlyAttendances = StaffAttendance::where('attendance_date', $date)
->where('check_in_time', '<>', null)
->where('check_out_time', '<>', null)
->where('check_out_time', '<', 'work_schedule_end')
->select();
$count = 0;
foreach ($earlyAttendances as $attendance) {
$attendance->status = 'early_departure';
$attendance->early_minutes = $this->calculateEarlyMinutes($attendance->check_out_time, $attendance->work_schedule_end);
$attendance->save();
$count++;
Log::write("员工早退:员工ID {$attendance->staff_id}, 早退 {$attendance->early_minutes} 分钟");
}
return ['count' => $count];
}
/**
* 处理缺勤状态
* @param string $date 日期
* @return array 处理结果
*/
protected function processAbsences($date)
{
$currentTime = date('H:i:s');
$absentThreshold = '18:30:00'; // 18:30后还未签到算缺勤
if ($currentTime < $absentThreshold) {
return ['count' => 0]; // 还没到判断缺勤的时间
}
// 查找今日全天未签到的员工
$absentAttendances = StaffAttendance::where('attendance_date', $date)
->where('check_in_time', null)
->where('status', '!=', 'leave') // 排除请假的员工
->select();
$count = 0;
foreach ($absentAttendances as $attendance) {
$attendance->status = 'absent';
$attendance->save();
$count++;
Log::write("员工缺勤:员工ID {$attendance->staff_id}, 日期: {$date}");
}
return ['count' => $count];
}
/**
* 计算工作时长
* @param string $date 日期
* @return array 处理结果
*/
protected function calculateWorkHours($date)
{
// 查找当日已完成签到签退的考勤记录
$completedAttendances = StaffAttendance::where('attendance_date', $date)
->where('check_in_time', '<>', null)
->where('check_out_time', '<>', null)
->where('work_hours', null) // 还未计算工作时长的
->select();
$count = 0;
foreach ($completedAttendances as $attendance) {
$workHours = $this->calculateHoursBetween($attendance->check_in_time, $attendance->check_out_time);
$attendance->work_hours = $workHours;
$attendance->save();
$count++;
Log::write("计算员工工作时长:员工ID {$attendance->staff_id}, 工作时长: {$workHours} 小时");
}
return ['count' => $count];
}
/**
* 计算迟到分钟数
* @param string $scheduleTime 计划时间
* @param string $actualTime 实际时间
* @return int 迟到分钟数
*/
protected function calculateLateMinutes($scheduleTime, $actualTime)
{
$schedule = strtotime($scheduleTime);
$actual = strtotime($actualTime);
if ($actual > $schedule) {
return intval(($actual - $schedule) / 60);
}
return 0;
}
/**
* 计算早退分钟数
* @param string $actualTime 实际时间
* @param string $scheduleTime 计划时间
* @return int 早退分钟数
*/
protected function calculateEarlyMinutes($actualTime, $scheduleTime)
{
$actual = strtotime($actualTime);
$schedule = strtotime($scheduleTime);
if ($schedule > $actual) {
return intval(($schedule - $actual) / 60);
}
return 0;
}
/**
* 计算两个时间之间的小时数
* @param string $startTime 开始时间
* @param string $endTime 结束时间
* @return float 小时数
*/
protected function calculateHoursBetween($startTime, $endTime)
{
$start = strtotime($startTime);
$end = strtotime($endTime);
if ($end > $start) {
return round(($end - $start) / 3600, 2);
}
return 0;
}
}