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
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;
|
|
}
|
|
}
|