argument('course_ids'); if (!preg_match('/^[1-9][0-9]*(,[1-9][0-9]*)*$/D', $raw)) { $this->error('课程ID必须为正整数,多个用英文逗号分隔。'); return 1; } $ids = array_values(array_unique(explode(',', $raw))); $courses = Course::whereIn('id', $ids); $found = (clone $courses)->get(['id', 'name', 'start_date']); $missingIds = array_diff($ids, $found->pluck('id')->all()); if ($missingIds) { $this->error('课程不存在或已删除:' . implode(',', $missingIds)); return 1; } // 缺少开课日期时无法确定历史入库时间,整批停止,避免只补一部分。 foreach ($found as $course) { if (!$course->start_date) { $this->error("课程 {$course->id}【{$course->name}】缺少开课日期,请先补全。"); return 1; } } $this->table(['课程ID', '课程名称', '开课日期'], $found->map(function ($course) { return [$course->id, $course->name, $course->start_date]; })->all()); $execute = (bool) $this->option('execute'); $this->info($execute ? '正式执行:仅补齐尚非校友的审核通过学员。' : '检查模式:不会修改任何学员数据。'); $total = 0; $updated = 0; $service->pendingUsers($courses)->chunkById(200, function ($users) use ($service, $execute, $ids, &$total, &$updated) { $rows = []; $courseInfo = $this->approvedCourseInfo($users->pluck('id')->all(), $ids); foreach ($users as $user) { $total++; $rows[] = [$user->id, $user->name, $user->mobile, $courseInfo[$user->id] ?? '', $user->source_start_date]; if ($execute) { $updated += $service->promote($user->id, $user->source_start_date); } } $this->table(['学员ID', '姓名', '手机号', '所选课程中审核通过的课程(ID/名称/开课日期)', '拟入库日期(所选课程最早开课日)'], $rows); }, 'users.id', 'id'); $this->info("发现遗漏 {$total} 人" . ($execute ? ",实际补齐 {$updated} 人。" : ';正式补齐请追加 --execute。')); $this->info('反向核对:当前是校友,但所选课程中没有未删除的审核通过记录。'); $this->line('此名单仅供核对,可能通过其他课程成为校友,不会取消校友资格。'); $outsideTotal = 0; User::where('is_schoolmate', 1) ->whereDoesntHave('courseSigns', function ($query) use ($ids) { $query->whereIn('course_id', $ids)->where('status', 1); }) ->chunkById(200, function ($users) use ($ids, &$outsideTotal) { $selectedInfo = $this->selectedEnrollmentInfo($users->pluck('id')->all(), $ids); $courseInfo = $this->approvedCourseInfo($users->pluck('id')->all()); $rows = []; foreach ($users as $user) { $outsideTotal++; $rows[] = [$user->id, $user->name, $user->mobile, $user->schoolmate_time, $selectedInfo[$user->id] ?? '无有效报名记录', $courseInfo[$user->id] ?? '无有效审核通过课程记录']; } $this->table(['学员ID', '姓名', '手机号', '入库时间', '所选课程报名情况(ID/名称/状态)', '其他审核通过课程(仅供核对,非入库来源证明)'], $rows); }); $this->info("所选课程无审核通过记录的校友共 {$outsideTotal} 人。"); return 0; } private function selectedEnrollmentInfo(array $userIds, array $courseIds): array { return CourseSign::query() ->join('courses', 'courses.id', '=', 'course_signs.course_id') ->whereNull('courses.deleted_at') ->whereIn('course_signs.user_id', $userIds) ->whereIn('course_signs.course_id', $courseIds) ->orderBy('courses.id')->orderBy('course_signs.id') ->get(['course_signs.user_id', 'course_signs.status', 'courses.id as course_id', 'courses.name']) ->groupBy('user_id')->map(function ($signs) { return $signs->map(function ($sign) { $status = CourseSign::$intToString['status'][$sign->status] ?? ('未知状态:' . $sign->status); return "{$sign->course_id}/{$sign->name}/{$status}"; })->unique()->implode("\n"); })->all(); } private function approvedCourseInfo(array $userIds, ?array $courseIds = null): array { $query = CourseSign::query() ->join('courses', 'courses.id', '=', 'course_signs.course_id') ->whereNull('courses.deleted_at') ->whereIn('course_signs.user_id', $userIds) ->where('course_signs.status', 1); if ($courseIds !== null) { $query->whereIn('course_signs.course_id', $courseIds); } return $query->orderBy('courses.start_date')->orderBy('courses.id') ->get(['course_signs.user_id', 'courses.id as course_id', 'courses.name', 'courses.start_date']) ->groupBy('user_id')->map(function ($signs) { return $signs->unique('course_id')->map(function ($sign) { return "{$sign->course_id}/{$sign->name}/{$sign->start_date}"; })->implode("\n"); })->all(); } }