diff --git a/app/Console/Commands/UpdateUserFromCourseSign.php b/app/Console/Commands/UpdateUserFromCourseSign.php index 2398bde..87dea4b 100644 --- a/app/Console/Commands/UpdateUserFromCourseSign.php +++ b/app/Console/Commands/UpdateUserFromCourseSign.php @@ -2,8 +2,11 @@ namespace App\Console\Commands; +use App\Models\Company; +use App\Models\Course; use App\Models\CourseForm; use App\Models\CourseSign; +use App\Models\CourseType; use App\Models\User; use Illuminate\Console\Command; use Illuminate\Support\Facades\Artisan; @@ -11,45 +14,11 @@ use Illuminate\Support\Facades\Artisan; class UpdateUserFromCourseSign extends Command { /** - * 限定的手机号列表 + * 课程体系优先级(高研班 > 攀峰班 > 初创班) * * @var array */ - protected $allowedMobiles = [ - '18068449126', - '13775025589', - '13372137856', - '15862529818', - '15850007903', - '18662477010', - '13776041671', - '13811803477', - '13816102853', - '18761927103', - '13771899330', - '15850174698', - '13901337246', - '15190599917', - '13601736904', - '18013537727', - '13771990129', - '13862584161', - '18067734553', - '13913088481', - '13382182663', - '15962537089', - '13472506601', - '15366527762', - '17306151525', - '18862122672', - '18768114864', - '13646251927', - '18068036921', - '13962165222', - '13812764284', - '17746389584', - '13813662822', - ]; + protected $courseTypePriority = ['高研班', '攀峰班', '初创班']; /** * The name and signature of the console command. @@ -63,7 +32,7 @@ class UpdateUserFromCourseSign extends Command * * @var string */ - protected $description = '从报名表获取用户填写的信息填充到user数据表(按手机号匹配)'; + protected $description = '从高研班/攀峰班/初创班报名表获取用户填写的信息,按优先级覆盖到user数据表'; /** * Create a new command instance. @@ -82,14 +51,32 @@ class UpdateUserFromCourseSign extends Command */ public function handle() { - // 根据限定手机号列表查找所有用户 - $users = User::whereIn('mobile', $this->allowedMobiles)->get(); + // 获取高研班、攀峰班、初创班三个课程体系下的课程 ID + $courseTypeIds = CourseType::whereIn('name', $this->courseTypePriority)->pluck('id')->toArray(); + if (empty($courseTypeIds)) { + return $this->error('未找到高研班/攀峰班/初创班课程类型'); + } - if ($users->isEmpty()) { - return $this->error('没有找到符合条件的用户'); + $courseIds = Course::whereIn('type', $courseTypeIds)->pluck('id')->toArray(); + if (empty($courseIds)) { + return $this->error('三个课程体系下没有课程'); } - $this->info("找到 {$users->count()} 个用户需要处理"); + // 获取这三个体系下所有有报名数据(data 不为空)的报名记录,再取去重用户 + $userIds = CourseSign::whereIn('course_id', $courseIds) + ->whereNotNull('user_id') + ->whereNotNull('data') + ->pluck('user_id') + ->unique() + ->values() + ->toArray(); + + if (empty($userIds)) { + return $this->error('没有找到符合条件的报名用户'); + } + + $users = User::whereIn('id', $userIds)->get(); + $this->info("找到 {$users->count()} 个用户需要处理(高研班/攀峰班/初创班报名用户)"); $successCount = 0; $failCount = 0; @@ -99,7 +86,7 @@ class UpdateUserFromCourseSign extends Command $this->info("========== 处理用户:{$user->name} (手机号: {$user->mobile}, ID: {$user->id}) =========="); try { - $this->processUser($user); + $this->processUser($user, $courseIds); $successCount++; } catch (\Exception $e) { $this->error("处理用户 {$user->name} 时出错:" . $e->getMessage()); @@ -113,100 +100,123 @@ class UpdateUserFromCourseSign extends Command /** * 处理单个用户 + * 按优先级(高研班 > 攀峰班 > 初创班)选定课程体系,取该体系下最新一条报名数据覆盖用户 + * + * @param \App\Models\User $user + * @param array $courseIds 高研班/攀峰班/初创班下的课程 ID 列表 */ - private function processUser($user) + private function processUser($user, array $courseIds) { $user_id = $user->id; - // 获取该用户的所有报名记录(携带课程及课程类型) + // 仅获取该用户在三个体系下的报名记录(携带课程及课程类型),按 created_at 倒序 $courseSigns = CourseSign::with('course.typeDetail') ->where('user_id', $user_id) + ->whereIn('course_id', $courseIds) ->whereNotNull('data') + ->orderByDesc('created_at') ->get(); if ($courseSigns->isEmpty()) { - $this->info('该用户没有报名记录或报名记录中没有数据'); + $this->info('该用户在此三个体系下没有报名记录或报名记录中没有数据'); return; } - $this->info("找到 {$courseSigns->count()} 条报名记录"); - - // 如果用户报名了多个课程,并且其中包含课程类型是「高研班」或者「攀峰班」的课程 - // 则优先使用这些课程的报名信息更新用户 - $targetCourseSigns = $courseSigns; - if ($courseSigns->count() > 1) { - $specialCourseSigns = $courseSigns->filter(function ($sign) { - $typeName = $sign->course->typeDetail->name ?? ''; - return in_array($typeName, ['高研班', '攀峰班']); + // 按优先级确定使用的课程体系:有高研班用高研班,否则攀峰班,否则初创班 + $selectedTypeName = null; + foreach ($this->courseTypePriority as $typeName) { + $hasSign = $courseSigns->contains(function ($sign) use ($typeName) { + $name = $sign->course->typeDetail->name ?? ''; + return $name === $typeName; }); - if ($specialCourseSigns->isNotEmpty()) { - $this->info('检测到高研班/攀峰班课程报名记录,将优先使用这些课程的报名信息更新用户'); - $targetCourseSigns = $specialCourseSigns; + if ($hasSign) { + $selectedTypeName = $typeName; + break; } } - // 收集所有需要更新的用户字段 + if ($selectedTypeName === null) { + $this->info('未匹配到高研班/攀峰班/初创班课程类型,跳过'); + return; + } + + // 只保留该体系下的报名,且已按 created_at 倒序,取最新一条 + $targetSigns = $courseSigns->filter(function ($sign) use ($selectedTypeName) { + $name = $sign->course->typeDetail->name ?? ''; + return $name === $selectedTypeName; + }); + $latestSign = $targetSigns->first(); + $this->info("使用课程体系【{$selectedTypeName}】下最新报名(course_sign_id: {$latestSign->id})覆盖用户数据"); + + // 从单条最新报名中提取用户字段 $userData = []; $hasCompanyName = false; - foreach ($targetCourseSigns as $courseSign) { - if (empty($courseSign->data) || !is_array($courseSign->data)) { - continue; - } + if (empty($latestSign->data) || !is_array($latestSign->data)) { + $this->info('该条报名 data 为空,无法更新用户'); + return; + } - // 获取该课程的表单字段配置,建立 field -> belong_user_table 的映射关系 - $courseForms = CourseForm::where('course_id', $courseSign->course_id) - ->where('belong_user', 1) // 只获取属于用户信息的字段 - ->whereNotNull('belong_user_table') // 必须有对应的用户表字段 - ->where('belong_user_table', '!=', '') // 用户表字段不能为空 - ->get(['field', 'belong_user_table']); + $courseForms = CourseForm::where('course_id', $latestSign->course_id) + ->where('belong_user', 1) + ->whereNotNull('belong_user_table') + ->where('belong_user_table', '!=', '') + ->get(['field', 'belong_user_table']); - if ($courseForms->isEmpty()) { - continue; - } + if ($courseForms->isEmpty()) { + $this->info('该课程无 belong_user 表单配置,跳过'); + return; + } + + $fieldMapping = []; + foreach ($courseForms as $form) { + $fieldMapping[$form->field] = $form->belong_user_table; + } - // 建立 field -> belong_user_table 的映射关系 - $fieldMapping = []; - foreach ($courseForms as $form) { - $fieldMapping[$form->field] = $form->belong_user_table; + $dataArray = []; + foreach ($latestSign->data as $item) { + if (isset($item['field'], $item['value'])) { + $dataArray[$item['field']] = $item['value']; } + } - // 将 data 数组转换为以 field 为 key 的关联数组 - $dataArray = []; - foreach ($courseSign->data as $item) { - if (isset($item['field']) && isset($item['value'])) { - $dataArray[$item['field']] = $item['value']; + foreach ($fieldMapping as $field => $userTableField) { + if (isset($dataArray[$field]) && $dataArray[$field] !== null && $dataArray[$field] !== '') { + $userData[$userTableField] = $dataArray[$field]; + if ($userTableField === 'company_name') { + $hasCompanyName = true; } } + } + + if (empty($userData)) { + $this->info('未解析出可更新的用户字段'); + return; + } - // 提取属于用户信息的字段,使用 belong_user_table 作为用户表的字段名 - foreach ($fieldMapping as $field => $userTableField) { - if (isset($dataArray[$field]) && $dataArray[$field] !== null && $dataArray[$field] !== '') { - // 如果字段已经在 $userData 中,且新值不为空,则更新(优先使用非空值) - if (!isset($userData[$userTableField]) || empty($userData[$userTableField])) { - $userData[$userTableField] = $dataArray[$field]; - } - - // 检查是否是公司名字 - if ($userTableField === 'company_name') { - $hasCompanyName = true; - } + // 如果用户已有 company_id 且存在对应的 company 数据,则不更新公司名字 + if ($user->company_id) { + $hasCompany = Company::where('id', $user->company_id)->exists(); + if ($hasCompany) { + // 有关联的 company 数据,移除 company_name 字段,不更新 + if (isset($userData['company_name'])) { + unset($userData['company_name']); + $hasCompanyName = false; + $this->info('用户已有关联的 company 数据(company_id: ' . $user->company_id . '),跳过公司名字更新'); } } } if (empty($userData)) { - $this->info('没有找到需要更新的用户信息'); + $this->info('移除公司名字后,没有其他需要更新的用户字段'); return; } $this->info('准备更新以下字段:' . implode(', ', array_keys($userData))); - // 更新用户信息 - // 根据 User::$coverFields 判断是否需要覆盖更新 + // 根据 User::$coverFields 判断覆盖或追加 foreach ($userData as $key => $value) { if (!in_array($key, User::$coverFields)) { - // 追加更新(对于非覆盖字段) $currentValue = $user->$key ?? ''; if (!empty($currentValue)) { $tempArray = explode(',', $currentValue . ',' . $value); @@ -216,10 +226,8 @@ class UpdateUserFromCourseSign extends Command } } - // 检查公司名字是否发生变化 $oldCompanyName = $user->company_name; $newCompanyName = $userData['company_name'] ?? null; - // 如果公司名字从无到有,或者发生变化,都需要更新 $companyNameChanged = $hasCompanyName && isset($newCompanyName) && (empty($oldCompanyName) || $oldCompanyName != $newCompanyName); @@ -228,7 +236,6 @@ class UpdateUserFromCourseSign extends Command $this->info('用户信息更新成功'); - // 如果公司名字发生变化或新增,调用 UpdateCompany 脚本 if ($companyNameChanged) { if (empty($oldCompanyName)) { $this->info("检测到新增公司名字({$newCompanyName}),开始调用 UpdateCompany 脚本更新公司信息...");