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.
272 lines
11 KiB
272 lines
11 KiB
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Niucloud-admin 企业快速开发的多应用管理平台
|
|
// +----------------------------------------------------------------------
|
|
// | 官方网址:https://www.niucloud.com
|
|
// +----------------------------------------------------------------------
|
|
// | niucloud团队 版权所有 开源版本可自由商用
|
|
// +----------------------------------------------------------------------
|
|
// | Author: Niucloud Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\job\transfer\schedule;
|
|
|
|
use app\model\course\Course;
|
|
use app\model\course_booking\CourseBooking;
|
|
use think\facade\Db;
|
|
use core\base\BaseJob;
|
|
use think\facade\Log;
|
|
|
|
/**
|
|
* 定时处理课程有效状态任务
|
|
* 检查课程的有效期,更新过期课程状态
|
|
*/
|
|
class CourseValidityJob extends BaseJob
|
|
{
|
|
/**
|
|
* 执行定时任务
|
|
* @param mixed ...$data 任务参数
|
|
* @return bool 处理结果
|
|
*/
|
|
public function doJob(...$data)
|
|
{
|
|
Log::write('开始执行课程有效状态检查任务');
|
|
|
|
try {
|
|
// 处理过期课程
|
|
$expiredResult = $this->processExpiredCourses();
|
|
|
|
// 处理孩子的固定课
|
|
$warningResult = $this->processStudentCourses();
|
|
|
|
Log::write('课程有效状态检查任务执行完成-' . print_r([
|
|
'expired_courses' => $expiredResult['count'],
|
|
'warning_courses' => $warningResult['count'],
|
|
], true));
|
|
|
|
return true;
|
|
|
|
} catch (\Exception $e) {
|
|
Log::write('课程有效状态检查任务执行失败:' . $e->getMessage());
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 处理课程的状态
|
|
* 根据school_course_schedule表的course_date和time_slot更新课程状态
|
|
* @return array 处理结果
|
|
*/
|
|
private function processExpiredCourses()
|
|
{
|
|
$currentDate = date('Y-m-d');
|
|
$currentTime = date('H:i:s');
|
|
$currentDateTime = date('Y-m-d H:i:s');
|
|
|
|
$count = 0;
|
|
|
|
try {
|
|
// 1. 更新已结束的课程 - course_date小于当前日期
|
|
$completedCount = Db::name('school_course_schedule')
|
|
->where('course_date', '<', $currentDate)
|
|
->where('status', '<>', 'completed')
|
|
->update([
|
|
'status' => 'completed',
|
|
'updated_at' => $currentDateTime
|
|
]);
|
|
|
|
Log::write("更新已结束课程数量: {$completedCount}");
|
|
$count += $completedCount;
|
|
|
|
// 2. 处理今天的课程,根据time_slot判断状态
|
|
$todaySchedules = Db::name('school_course_schedule')
|
|
->where('course_date', $currentDate)
|
|
->where('status', '<>', 'completed')
|
|
->select();
|
|
|
|
foreach ($todaySchedules as $schedule) {
|
|
$newStatus = $this->calculateCourseStatus($schedule['time_slot'], $currentTime);
|
|
|
|
if ($newStatus && $newStatus != $schedule['status']) {
|
|
Db::name('school_course_schedule')
|
|
->where('id', $schedule['id'])
|
|
->update([
|
|
'status' => $newStatus,
|
|
'updated_at' => $currentDateTime
|
|
]);
|
|
|
|
$count++;
|
|
Log::write("更新课程状态: ID {$schedule['id']}, 时间段 {$schedule['time_slot']}, 状态 {$schedule['status']} -> {$newStatus}");
|
|
}
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
Log::write('处理课程状态失败: ' . $e->getMessage());
|
|
throw $e;
|
|
}
|
|
|
|
return ['count' => $count];
|
|
}
|
|
|
|
/**
|
|
* 处理学员固定课的安排
|
|
* 查看school_person_course_schedule表中schedule_type=2且person_type=student的课程
|
|
* 自动为下周相同时间新增上课记录
|
|
* @return array 处理结果
|
|
*/
|
|
private function processStudentCourses()
|
|
{
|
|
$currentDate = date('Y-m-d');
|
|
$currentDateTime = date('Y-m-d H:i:s');
|
|
$count = 0;
|
|
|
|
try {
|
|
// 查找学员的固定课程安排
|
|
$studentFixedCourses = Db::name('school_person_course_schedule')
|
|
->where('schedule_type', 2)
|
|
->where('person_type', 'student')
|
|
->where('status', 1) // 假设1为有效状态
|
|
->select();
|
|
|
|
foreach ($studentFixedCourses as $studentCourse) {
|
|
// 通过schedule_id获取课程安排信息
|
|
$courseSchedule = Db::name('school_course_schedule')
|
|
->where('id', $studentCourse['schedule_id'])
|
|
->find();
|
|
|
|
if (!$courseSchedule) {
|
|
continue;
|
|
}
|
|
|
|
// 计算下周同一天的日期
|
|
$courseDate = $courseSchedule['course_date'];
|
|
$dayOfWeek = date('w', strtotime($courseDate)); // 0(周日)到6(周六)
|
|
$nextWeekDate = $this->getNextWeekSameDay($courseDate);
|
|
|
|
// 检查下周那天是否有相同时间段的课程安排
|
|
$nextWeekSchedule = Db::name('school_course_schedule')
|
|
->where('course_date', $nextWeekDate)
|
|
->where('time_slot', $courseSchedule['time_slot'])
|
|
->where('venue_id', $courseSchedule['venue_id']) // 同一场地
|
|
->find();
|
|
|
|
if ($nextWeekSchedule) {
|
|
// 检查该学员是否已经有下周的上课记录
|
|
$existingRecord = Db::name('school_person_course_schedule')
|
|
->where('person_id', $studentCourse['person_id'])
|
|
->where('schedule_id', $nextWeekSchedule['id'])
|
|
->where('person_type', 'student')
|
|
->count();
|
|
|
|
if ($existingRecord == 0) {
|
|
// 为学员新增下周的上课记录
|
|
$newRecord = [
|
|
'person_id' => $studentCourse['person_id'],
|
|
'schedule_id' => $nextWeekSchedule['id'],
|
|
'person_type' => 'student',
|
|
'schedule_type' => 2, // 固定课
|
|
'status' => 1,
|
|
'created_at' => $currentDateTime,
|
|
'updated_at' => $currentDateTime
|
|
];
|
|
|
|
// 复制其他可能的字段
|
|
if (isset($studentCourse['course_id'])) {
|
|
$newRecord['course_id'] = $studentCourse['course_id'];
|
|
}
|
|
if (isset($studentCourse['venue_id'])) {
|
|
$newRecord['venue_id'] = $studentCourse['venue_id'];
|
|
}
|
|
|
|
Db::name('school_person_course_schedule')->insert($newRecord);
|
|
|
|
$count++;
|
|
Log::write("为学员新增下周固定课: 学员ID {$studentCourse['person_id']}, 日期 {$nextWeekDate}, 时间段 {$courseSchedule['time_slot']}");
|
|
}
|
|
} else {
|
|
Log::write("下周无对应课程安排,跳过: 日期 {$nextWeekDate}, 时间段 {$courseSchedule['time_slot']}");
|
|
}
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
Log::write('处理学员固定课安排失败: ' . $e->getMessage());
|
|
throw $e;
|
|
}
|
|
|
|
return ['count' => $count];
|
|
}
|
|
|
|
/**
|
|
* 根据时间段和当前时间计算课程状态
|
|
* @param string $timeSlot 时间段,格式如 "11:30-12:30"
|
|
* @param string $currentTime 当前时间,格式如 "14:30:00"
|
|
* @return string|null 课程状态:upcoming, ongoing, completed 或 null(无需更新)
|
|
*/
|
|
private function calculateCourseStatus($timeSlot, $currentTime)
|
|
{
|
|
if (empty($timeSlot)) {
|
|
return null;
|
|
}
|
|
|
|
// 解析时间段,格式如 "11:30-12:30"
|
|
$timeParts = explode('-', $timeSlot);
|
|
if (count($timeParts) != 2) {
|
|
Log::write("时间段格式错误: {$timeSlot}");
|
|
return null;
|
|
}
|
|
|
|
$startTime = trim($timeParts[0]) . ':00'; // 转换为 "11:30:00"
|
|
$endTime = trim($timeParts[1]) . ':00'; // 转换为 "12:30:00"
|
|
|
|
$currentTimestamp = strtotime($currentTime);
|
|
$startTimestamp = strtotime($startTime);
|
|
$endTimestamp = strtotime($endTime);
|
|
$sixHoursBeforeStart = $startTimestamp - (6 * 3600); // 开始时间前6小时
|
|
|
|
if ($currentTimestamp <= $sixHoursBeforeStart) {
|
|
// 当前时间距离开始时间超过6小时,不需要更新状态
|
|
return null;
|
|
} elseif ($currentTimestamp <= $startTimestamp) {
|
|
// 当前时间在开始前6小时内,状态为即将开始
|
|
return 'upcoming';
|
|
} elseif ($currentTimestamp >= $startTimestamp && $currentTimestamp <= $endTimestamp) {
|
|
// 当前时间在课程时间范围内,状态为进行中
|
|
return 'ongoing';
|
|
} elseif ($currentTimestamp > $endTimestamp) {
|
|
// 当前时间已过结束时间,状态为已结束
|
|
return 'completed';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 计算下周同一天的日期
|
|
* @param string $courseDate 课程日期,格式如 "2025-01-08"
|
|
* @return string 下周同一天的日期
|
|
*/
|
|
private function getNextWeekSameDay($courseDate)
|
|
{
|
|
$timestamp = strtotime($courseDate);
|
|
$nextWeekTimestamp = $timestamp + (7 * 24 * 3600); // 加7天
|
|
return date('Y-m-d', $nextWeekTimestamp);
|
|
}
|
|
|
|
/**
|
|
* 发送课程即将过期的警告通知
|
|
* @param Course $course 课程对象
|
|
*/
|
|
protected function sendExpiryWarning($course)
|
|
{
|
|
// 这里可以实现具体的通知逻辑
|
|
// 比如发送邮件、短信、系统内通知等
|
|
Log::write("发送过期提醒通知:课程 {$course->course_name} 将在 {$course->valid_until} 过期");
|
|
|
|
// 示例:可以调用通知服务
|
|
// NotificationService::send([
|
|
// 'type' => 'course_expiry_warning',
|
|
// 'course_id' => $course->id,
|
|
// 'message' => "您的课程《{$course->course_name}》将在{$course->valid_until}过期"
|
|
// ]);
|
|
}
|
|
}
|