智慧教务系统
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.
 
 
 
 
 
 

403 lines
13 KiB

<?php
namespace app\service\api\student;
use app\model\school\SchoolPersonCourseSchedule;
use app\model\school\SchoolStudentCourseUsage;
use app\model\school\SchoolStudentCourses;
use app\model\school\SchoolStudent;
use core\base\BaseApiService;
use think\facade\Db;
/**
* 学员出勤服务类
*/
class AttendanceService extends BaseApiService
{
public function __construct()
{
parent::__construct();
}
/**
* 学员签到
* @param array $data
* @return array
*/
public function checkinStudent($data)
{
$schedule_id = $data['schedule_id'];
$student_id = $data['student_id'];
$student = (new SchoolStudent())
->where('id', $student_id)
->find();
$resources_id = $student->user_id;
$person_id = $this->member_id;
if (empty($schedule_id)) {
throw new \Exception('参数错误:缺少课程安排ID');
}
// 开启事务
Db::startTrans();
try {
// 1. 查询课程安排记录 - 支持学员和客户资源两种类型
$where = [
['schedule_id', '=', $schedule_id],
['student_id', '=', $student_id],
['resources_id', '=', $resources_id],
['deleted_at', '=', 0]
];
$schedule = (new SchoolPersonCourseSchedule())
->where($where)
->find();
if (!$schedule) {
throw new \Exception('课程安排记录不存在');
}
if ($schedule['status'] == 1) {
throw new \Exception('该学员已经签到过了');
}
// 2. 更新课程安排状态为已上课
$schedule->save([
'status' => 1,
'updated_at' => time()
]);
$student_course_id = $schedule['student_course_id'];
$person_type = $schedule['person_type'];
if (!empty($student_course_id)) {
// 正式学员处理逻辑
$this->handleFormalStudentCheckin($student_course_id, $student_id, $schedule);
} elseif ($person_type == 'student' && !empty($student_id)) {
// 体验课学员处理逻辑
$this->handleTrialStudentCheckin($student_id, $schedule);
} elseif ($person_type == 'customer_resource') {
// 客户资源处理逻辑 - 只更新状态,不扣除课时
$this->handleCustomerResourceCheckin($schedule);
} else {
throw new \Exception('无法确定人员类型,签到失败');
}
Db::commit();
return [
'schedule_id' => $schedule_id,
'student_id' => $student_id,
'status' => 1,
'message' => '签到成功'
];
} catch (\Exception $e) {
Db::rollback();
throw new \Exception('签到失败:' . $e->getMessage());
}
}
/**
* 处理正式学员签到
* @param int $student_course_id
* @param int $student_id
* @param object $schedule
*/
private function handleFormalStudentCheckin($student_course_id, $student_id, $schedule)
{
// 查询学员课程信息
$studentCourse = (new SchoolStudentCourses())
->where('id', $student_course_id)
->find();
if (!$studentCourse) {
throw new \Exception('学员课程记录不存在');
}
$single_session_count = $studentCourse['single_session_count'] ?: 1;
$total_hours = $studentCourse['total_hours'];
$gift_hours = $studentCourse['gift_hours'];
$use_total_hours = $studentCourse['use_total_hours'];
$use_gift_hours = $studentCourse['use_gift_hours'];
// 计算课时扣减逻辑
$remaining_total_hours = $total_hours - $use_total_hours;
$remaining_gift_hours = $gift_hours - $use_gift_hours;
$new_use_total_hours = $use_total_hours;
$new_use_gift_hours = $use_gift_hours;
if ($remaining_total_hours > 0) {
// 优先扣减正式课时
$deduct_from_total = min($remaining_total_hours, $single_session_count);
$new_use_total_hours += $deduct_from_total;
$remaining_to_deduct = $single_session_count - $deduct_from_total;
if ($remaining_to_deduct > 0 && $remaining_gift_hours > 0) {
// 剩余部分从赠送课时扣减
$deduct_from_gift = min($remaining_gift_hours, $remaining_to_deduct);
$new_use_gift_hours += $deduct_from_gift;
}
} else if ($remaining_gift_hours > 0) {
// 没有正式课时,直接扣减赠送课时
$deduct_from_gift = min($remaining_gift_hours, $single_session_count);
$new_use_gift_hours += $deduct_from_gift;
}
// 更新学员课程表
$studentCourse->save([
'use_total_hours' => $new_use_total_hours,
'use_gift_hours' => $new_use_gift_hours,
'updated_at' => time()
]);
// 插入消课记录
$this->insertUsageRecord($student_course_id, $student_id, $single_session_count, $schedule);
}
/**
* 处理体验课学员签到
* @param int $student_id
* @param object $schedule
*/
private function handleTrialStudentCheckin($student_id, $schedule)
{
// 查询学员信息
$student = (new SchoolStudent())
->where('id', $student_id)
->find();
if (!$student) {
throw new \Exception('学员信息不存在');
}
$updateData = [];
$current_time = time();
// 更新到校时间逻辑
if (empty($student['first_come'])) {
$updateData['first_come'] = $current_time;
} else if (empty($student['second_come'])) {
$updateData['second_come'] = $current_time;
}
// 扣减体验课次数
$trial_class_count = $student['trial_class_count'] ?: 0;
if ($trial_class_count > 0) {
$updateData['trial_class_count'] = $trial_class_count - 1;
}
if (!empty($updateData)) {
$updateData['updated_at'] = date('Y-m-d H:i:s');
$student->save($updateData);
}
// 插入消课记录(体验课也需要记录)
$this->insertUsageRecord(0, $student_id, 1, $schedule);
}
/**
* 插入消课记录
* @param int $student_course_id
* @param int $student_id
* @param float $used_hours
* @param object $schedule
*/
private function insertUsageRecord($student_course_id, $student_id, $used_hours, $schedule)
{
// 获取资源ID
$resource_id = $schedule['resources_id'];
(new SchoolStudentCourseUsage())->save([
'student_course_id' => $student_course_id,
'used_hours' => $used_hours,
'usage_date' => date('Y-m-d'),
'student_id' => $student_id,
'resource_id' => $resource_id,
'created_at' => time(),
'updated_at' => time()
]);
}
/**
* 学员请假
* @param array $data
* @return array
*/
public function leaveStudent($data)
{
$schedule_id = $data['schedule_id'];
$student_id = $data['student_id'];
$resources_id = $data['resources_id'] ?? 0;
$person_id = $data['person_id'];
$remark = $data['remark'] ?? '';
if (empty($schedule_id)) {
throw new \Exception('参数错误:缺少课程安排ID');
}
// 查询课程安排记录 - 支持学员和客户资源两种类型
$where = [
['schedule_id', '=', $schedule_id],
['person_id', '=', $person_id],
['deleted_at', '=', 0]
];
// 根据传入的参数决定查询条件
if (!empty($student_id) && $student_id > 0) {
// 正式学员
$where[] = ['student_id', '=', $student_id];
$where[] = ['person_type', '=', 'student'];
} elseif (!empty($resources_id) && $resources_id > 0) {
// 客户资源
$where[] = ['resources_id', '=', $resources_id];
$where[] = ['person_type', '=', 'customer_resource'];
} else {
throw new \Exception('参数错误:必须提供学员ID或资源ID');
}
$schedule = (new SchoolPersonCourseSchedule())
->where($where)
->find();
if (!$schedule) {
throw new \Exception('课程安排记录不存在');
}
if ($schedule['status'] == 2) {
throw new \Exception('该学员已经请假了');
}
// 更新状态为请假
$schedule->save([
'status' => 2,
'remark' => $remark,
'updated_at' => time()
]);
return [
'schedule_id' => $schedule_id,
'student_id' => $student_id,
'status' => 2,
'message' => '请假成功'
];
}
/**
* 学员取消
* @param array $data
* @return array
*/
public function cancelStudent($data)
{
$schedule_id = $data['schedule_id'];
$student_id = $data['student_id'];
$resources_id = $data['resources_id'] ?? 0;
$person_id = $data['person_id'];
$cancel_scope = $data['cancel_scope'] ?? 'single'; // single: 单节课, all: 全部课程
$cancel_reason = $data['cancel_reason'] ?? '';
if (empty($schedule_id)) {
throw new \Exception('参数错误:缺少课程安排ID');
}
// 开启事务
Db::startTrans();
try {
// 查询课程安排记录 - 支持学员和客户资源两种类型
$where = [
['schedule_id', '=', $schedule_id],
['person_id', '=', $person_id],
['deleted_at', '=', 0]
];
// 根据传入的参数决定查询条件
if (!empty($student_id) && $student_id > 0) {
// 正式学员
$where[] = ['student_id', '=', $student_id];
$where[] = ['person_type', '=', 'student'];
} elseif (!empty($resources_id) && $resources_id > 0) {
// 客户资源
$where[] = ['resources_id', '=', $resources_id];
$where[] = ['person_type', '=', 'customer_resource'];
} else {
throw new \Exception('参数错误:必须提供学员ID或资源ID');
}
$schedule = (new SchoolPersonCourseSchedule())
->where($where)
->find();
if (!$schedule) {
throw new \Exception('课程安排记录不存在');
}
$schedule_type = $schedule['schedule_type'];
$course_date = $schedule['course_date'];
$current_time = time();
if ($cancel_scope === 'all' && $schedule_type == 1) {
// 批量取消固定课程
$cancelCount = (new SchoolPersonCourseSchedule())
->where([
['student_id', '=', $student_id],
['schedule_id', '=', $schedule_id],
['course_date', '>=', $course_date],
['deleted_at', '=', 0]
])
->update([
'deleted_at' => $current_time,
'cancel_reason' => $cancel_reason,
'updated_at' => $current_time
]);
$message = "成功取消{$cancelCount}节固定课程";
} else {
// 单节课取消
$schedule->save([
'deleted_at' => $current_time,
'cancel_reason' => $cancel_reason,
'updated_at' => $current_time
]);
$message = '成功取消单节课程';
}
Db::commit();
return [
'schedule_id' => $schedule_id,
'student_id' => $student_id,
'cancel_scope' => $cancel_scope,
'message' => $message
];
} catch (\Exception $e) {
Db::rollback();
throw new \Exception('取消失败:' . $e->getMessage());
}
}
/**
* 处理客户资源签到
* @param object $schedule
*/
private function handleCustomerResourceCheckin($schedule)
{
// 客户资源签到只需要更新状态,不涉及课时扣除
// 状态已经在主流程中更新了,这里可以记录签到日志或其他业务逻辑
// 可以在这里添加客户资源的特殊处理逻辑
// 比如记录体验课次数、更新客户跟进状态等
$current_time = time();
// 如果需要更新客户资源相关信息,可以在这里添加
// 例如:更新体验课次数、最后上课时间等
return true;
}
}