allowedCourseTypeNames; $allowedCourseNames = $this->allowedCourseNames; $fixedUsers = User::query() ->where('is_schoolmate', 1) ->where(function ($query) { $query->whereNull('mobile') ->orWhere('mobile', ''); }) ->orderBy('id') ->get(); $fixedCount = 0; foreach ($fixedUsers as $user) { $user->is_schoolmate = 0; $user->schoolmate_time = null; if ($user->isDirty()) { $user->save(); $fixedCount++; } } $invalidUsers = User::query() ->where('is_schoolmate', 1) ->whereDoesntHave('courseSigns', function ($query) use ($today, $allowedCourseTypeNames, $allowedCourseNames) { $query->where('status', 1) ->whereHas('course', function ($courseQuery) use ($today, $allowedCourseTypeNames, $allowedCourseNames) { $courseQuery->where(function ($eligibleQuery) use ($today, $allowedCourseTypeNames, $allowedCourseNames) { $eligibleQuery->where(function ($autoSchoolmateQuery) use ($today) { $autoSchoolmateQuery->where('auto_schoolmate', 1) ->whereNotNull('start_date') ->where('start_date', '<=', $today); })->orWhereHas('typeDetail', function ($typeQuery) use ($allowedCourseTypeNames) { $typeQuery->whereIn('name', $allowedCourseTypeNames); })->orWhereIn('name', $allowedCourseNames); }); }); }) ->with([ 'courseSigns' => function ($query) { $query->where('status', 1)->with('course.typeDetail'); } ]) ->orderBy('id') ->get(); $schoolmateTotal = User::where('is_schoolmate', 1)->count(); $invalidCount = $invalidUsers->count(); $this->info("当前校友总数:{$schoolmateTotal}"); $this->info("已自动修正无手机号但仍是校友的用户数:{$fixedCount}"); $this->info('检测口径:用户当前是校友,但不存在以下任一合格来源,则判定为不符合要求:'); $this->line('1. 已审核通过,且课程开启自动入校友,且课程已开课'); $this->line('2. 已审核通过,且课程属于高研班体系'); $this->line('3. 已审核通过,且课程属于攀峰班体系'); $this->line('4. 已审核通过,且课程为“首期技术经理人领航班”'); if ($invalidUsers->isEmpty()) { $this->info('检测完成:当前所有校友数据都符合校友认定规则。'); return self::SUCCESS; } $this->warn('检测完成:发现 ' . $invalidCount . ' 位校友不符合校友认定规则,以下用户将被自动取消校友身份。'); $this->newLine(); $rows = []; foreach ($invalidUsers as $user) { $passedCourses = $user->courseSigns ->map(function ($courseSign) use ($allowedCourseTypeNames, $allowedCourseNames, $today) { if (empty($courseSign->course)) { return '课程已删除'; } $course = $courseSign->course; $courseTypeName = $course->typeDetail->name ?? '空'; $reasons = []; if ($course->auto_schoolmate == 1 && !empty($course->start_date) && $course->start_date <= $today) { $reasons[] = '自动入校友'; } if (in_array($courseTypeName, $allowedCourseTypeNames, true)) { $reasons[] = '体系白名单'; } if (in_array($course->name, $allowedCourseNames, true)) { $reasons[] = '课程白名单'; } return sprintf( '%s[课程体系=%s,auto_schoolmate=%s,start_date=%s,命中规则=%s]', $course->name, $courseTypeName, (string) $course->auto_schoolmate, $course->start_date ?: '空', empty($reasons) ? '无' : implode('+', $reasons) ); }) ->filter() ->unique() ->values() ->implode(';'); $rows[] = [ '用户ID' => $user->id, '姓名' => $user->name, '手机号' => $user->mobile, '成为校友时间' => $user->schoolmate_time ?: '空', '已通过课程' => $passedCourses ?: '无', '不符合原因' => '没有符合自动入校友规则的已通过课程', ]; } $this->table( ['用户ID', '姓名', '手机号', '成为校友时间', '已通过课程', '不符合原因'], $rows ); $updatedCount = 0; foreach ($invalidUsers as $user) { $user->is_schoolmate = 0; $user->schoolmate_time = null; if ($user->isDirty()) { $user->save(); $updatedCount++; } } $this->newLine(); $this->info("已自动取消 {$updatedCount} 位异常校友的校友身份。"); $this->info('本次仅在命令行输出处理结果,不再生成 txt 文件。'); return self::SUCCESS; } }