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

4 weeks ago
<?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()
4 weeks ago
->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');
}
4 weeks ago
public function ineligibleSchoolmates($courses)
{
4 weeks ago
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;
});
4 weeks ago
}
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);
});
}
}