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.

262 lines
9.4 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\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;
class UpdateUserFromCourseSign extends Command
{
/**
* 课程体系优先级(高研班 > 攀峰班 > 初创班)
*
* @var array
*/
protected $courseTypePriority = ['高研班', '攀峰班', '初创班'];
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'update_user_from_course_sign';
/**
* The console command description.
*
* @var string
*/
protected $description = '从高研班/攀峰班/初创班报名表获取用户填写的信息按优先级覆盖到user数据表';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// 获取高研班、攀峰班、初创班三个课程体系下的课程 ID
$courseTypeIds = CourseType::whereIn('name', $this->courseTypePriority)->pluck('id')->toArray();
if (empty($courseTypeIds)) {
return $this->error('未找到高研班/攀峰班/初创班课程类型');
}
$courseIds = Course::whereIn('type', $courseTypeIds)->pluck('id')->toArray();
if (empty($courseIds)) {
return $this->error('三个课程体系下没有课程');
}
// 获取这三个体系下所有有报名数据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;
foreach ($users as $user) {
$this->newLine();
$this->info("========== 处理用户:{$user->name} (手机号: {$user->mobile}, ID: {$user->id}) ==========");
try {
$this->processUser($user, $courseIds);
$successCount++;
} catch (\Exception $e) {
$this->error("处理用户 {$user->name} 时出错:" . $e->getMessage());
$failCount++;
}
}
$this->newLine();
return $this->info("全部处理完成!成功:{$successCount},失败:{$failCount}");
}
/**
* 处理单个用户
* 按优先级(高研班 > 攀峰班 > 初创班)选定课程体系,取该体系下最新一条报名数据覆盖用户
*
* @param \App\Models\User $user
* @param array $courseIds 高研班/攀峰班/初创班下的课程 ID 列表
*/
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('该用户在此三个体系下没有报名记录或报名记录中没有数据');
return;
}
// 统计用户报名的课程体系
$userCourseTypes = $courseSigns->map(function ($sign) {
return $sign->course->typeDetail->name ?? '';
})->filter()->unique()->values()->toArray();
$this->info('用户报名的课程体系:' . implode('、', $userCourseTypes));
// 按优先级确定使用的课程体系:有高研班用高研班,否则攀峰班,否则初创班
$selectedTypeName = null;
foreach ($this->courseTypePriority as $typeName) {
$hasSign = $courseSigns->contains(function ($sign) use ($typeName) {
$name = $sign->course->typeDetail->name ?? '';
return $name === $typeName;
});
if ($hasSign) {
$selectedTypeName = $typeName;
$this->info("检测到用户报名了【{$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;
if (empty($latestSign->data) || !is_array($latestSign->data)) {
$this->info('该条报名 data 为空,无法更新用户');
return;
}
$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()) {
$this->info('该课程无 belong_user 表单配置,跳过');
return;
}
$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'];
}
}
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;
}
// 如果用户已有 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('移除公司名字后,没有其他需要更新的用户字段');
return;
}
$this->info('准备更新以下字段:' . implode(', ', array_keys($userData)));
// 根据 User::$coverFields 判断覆盖或追加
foreach ($userData as $key => $value) {
if (!in_array($key, User::$coverFields)) {
$currentValue = $user->$key ?? '';
if (!empty($currentValue)) {
$tempArray = explode(',', $currentValue . ',' . $value);
$tempArray = array_unique(array_filter($tempArray));
$userData[$key] = implode(',', $tempArray);
}
}
}
$oldCompanyName = $user->company_name;
$newCompanyName = $userData['company_name'] ?? null;
$companyNameChanged = $hasCompanyName && isset($newCompanyName) &&
(empty($oldCompanyName) || $oldCompanyName != $newCompanyName);
$user->fill($userData);
$user->save();
$this->info('用户信息更新成功');
if ($companyNameChanged) {
if (empty($oldCompanyName)) {
$this->info("检测到新增公司名字({$newCompanyName}),开始调用 UpdateCompany 脚本更新公司信息...");
} else {
$this->info("检测到公司名字发生变化({$oldCompanyName} -> {$newCompanyName}),开始调用 UpdateCompany 脚本更新公司信息...");
}
Artisan::call("update_company --user_id={$user_id}");
$this->info('公司信息更新完成');
} elseif ($hasCompanyName && isset($newCompanyName)) {
$this->info("公司名字未发生变化({$newCompanyName}),跳过公司信息更新");
}
$this->info('用户更新完成');
}
}