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.
wx.sstbc.com/app/Services/SchoolmateEnrollmentService...

95 lines
3.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Services;
use App\Models\Course;
use App\Models\CourseSign;
use App\Models\User;
use Illuminate\Support\Facades\DB;
class SchoolmateEnrollmentService
{
/**
* 仅选择未删除、尚未成为校友且有有效审核通过报名的学员。
* 多门课程取最早开课日期;指定课程补齐不受自动入库开关限制。
*/
public function pendingUsers($courses)
{
return User::query()
->joinSub($this->eligibleSources($courses), 'schoolmate_sources', function ($join) {
$join->on('users.id', '=', 'schoolmate_sources.user_id');
})
->whereRaw('COALESCE(users.is_schoolmate, 0) != 1')
->select('users.*', 'schoolmate_sources.source_start_date');
}
private function eligibleSources($courses)
{
return CourseSign::query()
->join('courses', 'courses.id', '=', 'course_signs.course_id')
->whereNull('courses.deleted_at')
->whereIn('courses.id', (clone $courses)->select('courses.id'))
->where('course_signs.status', 1)
->select('course_signs.user_id')
->selectRaw('MIN(courses.start_date) as source_start_date')
->groupBy('course_signs.user_id');
}
public function ineligibleSchoolmates($courses)
{
return User::query()
->where('users.is_schoolmate', 1)
->whereNotIn('users.id', $this->eligibleSources($courses)
->select('course_signs.user_id')->whereNotNull('course_signs.user_id'));
}
/**
* 锁定用户后重新核验,避免按批次查询时取得的旧资格更新用户。
* 返回 1 表示入库,-1 表示取消,0 表示无需变更。
*/
public function reconcile(int $userId, $courses): int
{
return DB::transaction(function () use ($userId, $courses) {
$user = User::whereKey($userId)->lockForUpdate()->first();
if (!$user) {
return 0;
}
$source = $this->eligibleSources($courses)
->where('course_signs.user_id', $userId)->first();
if ($source && $user->is_schoolmate != 1) {
return User::batchUpdateToSchoolmate([$userId], $source->source_start_date);
}
if (!$source && $user->is_schoolmate == 1) {
$user->is_schoolmate = 0;
$user->schoolmate_time = null;
return $user->save() ? -1 : 0;
}
return 0;
});
}
public function automaticCourses()
{
// 保留开课前一天入库的原行为,同时补查历史及开课后审核通过的学员。
return Course::where('auto_schoolmate', 1)
->whereNotNull('start_date')
->whereDate('start_date', '<=', now()->addDay()->toDateString());
}
public function promote(int $userId, string $startDate): int
{
return DB::transaction(function () use ($userId, $startDate) {
// 手工补齐和自动任务同时运行时,不覆盖已有校友的入库时间。
$user = User::whereKey($userId)->lockForUpdate()->first();
if (!$user || $user->is_schoolmate == 1) {
return 0;
}
return User::batchUpdateToSchoolmate([$userId], $startDate);
});
}
}