|
|
|
|
@ -3,231 +3,294 @@
|
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
|
|
|
|
|
|
use App\Models\Course;
|
|
|
|
|
use App\Models\CourseSign;
|
|
|
|
|
use App\Models\CourseType;
|
|
|
|
|
use App\Models\CourseTypeDataOverviewConfig;
|
|
|
|
|
use App\Models\HistoryCourse;
|
|
|
|
|
use App\Models\CourseSign;
|
|
|
|
|
use Illuminate\Console\Command;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 对比 home-v2 的 yearConfigs 与 courses-home 的 courseTypesSum
|
|
|
|
|
* 在 2024-01-01 ~ 2027-01-01 时间段内,找出课程数量、去重培养人数差异的原因
|
|
|
|
|
* 比对 home-v2 的 yearConfigs 与 courses-home 的 courseTypesSum,
|
|
|
|
|
* 在指定时间段内 期数、课程数量、去重培养人数 的差异,并输出导致差异的 Course / HistoryCourse 明细。
|
|
|
|
|
*/
|
|
|
|
|
class DiffHomeV2CoursesHome extends Command
|
|
|
|
|
{
|
|
|
|
|
protected $signature = 'diff:home-v2-courses-home {--start=2024-01-01} {--end=2027-01-01}';
|
|
|
|
|
protected $description = '对比 home-v2 yearConfigs 与 courses-home courseTypesSum 在指定时间段内的期数、去重培养人数差异';
|
|
|
|
|
|
|
|
|
|
public function handle()
|
|
|
|
|
{
|
|
|
|
|
$start = $this->option('start');
|
|
|
|
|
$end = $this->option('end');
|
|
|
|
|
$this->info("=== 对比时间段: {$start} ~ {$end} ===\n");
|
|
|
|
|
|
|
|
|
|
// 1. 找到覆盖该时间段的 yearConfig(或使用该时间段模拟)
|
|
|
|
|
$config = CourseTypeDataOverviewConfig::where('status', true)
|
|
|
|
|
->where('start_date', '<=', $start)
|
|
|
|
|
->where(function ($q) use ($end) {
|
|
|
|
|
$q->where('end_date', '>=', $end)->orWhereNull('end_date');
|
|
|
|
|
})
|
|
|
|
|
->orderBy('sort')
|
|
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
if (!$config) {
|
|
|
|
|
$config = CourseTypeDataOverviewConfig::where('status', true)
|
|
|
|
|
->whereBetween('start_date', [$start, $end])
|
|
|
|
|
->orWhereBetween('end_date', [$start, $end])
|
|
|
|
|
->orderBy('sort')
|
|
|
|
|
->first();
|
|
|
|
|
}
|
|
|
|
|
protected $signature = 'diff:home-v2-courses-home
|
|
|
|
|
{--start=2024-01-01 : 开始日期}
|
|
|
|
|
{--end=2027-01-01 : 结束日期}
|
|
|
|
|
{--config-id= : 可选,仅用该 yearConfig 的日期;不传则用 start/end}';
|
|
|
|
|
|
|
|
|
|
$configStart = $config ? $config->start_date : $start;
|
|
|
|
|
$configEnd = $config && $config->end_date ? $config->end_date : $end;
|
|
|
|
|
$this->info("yearConfig: " . ($config ? "id={$config->id} [{$configStart} ~ {$configEnd}]" : "无覆盖配置,使用 {$configStart} ~ {$configEnd}"));
|
|
|
|
|
protected $description = '比对 home-v2(yearConfigs) 与 courses-home(courseTypesSum) 的期数、课程数量、去重培养人数差异';
|
|
|
|
|
|
|
|
|
|
// 2. 按 home-v2 逻辑统计(仅用 2024-01-01~2027-01-01 做筛选,与 config 自身范围不一致时以 2024-2027 为准则需单独算)
|
|
|
|
|
// 为与 courses-home 可比,我们在这里用 start~end 作为统一日期范围
|
|
|
|
|
$homeV2 = $this->computeHomeV2Style($start, $end);
|
|
|
|
|
$this->info("\n【home-v2 逻辑】期数: {$homeV2['course_periods_total']}, 去重培养人数: {$homeV2['course_signs_unique_total']}");
|
|
|
|
|
protected $startDate;
|
|
|
|
|
protected $endDate;
|
|
|
|
|
|
|
|
|
|
// 3. 按 courses-home 逻辑统计
|
|
|
|
|
$coursesHome = $this->computeCoursesHomeStyle($start, $end);
|
|
|
|
|
$this->info("【courses-home 逻辑】课程数量(行数): {$coursesHome['course_count']}, 去重培养人数: {$coursesHome['course_signs_unique_total']}");
|
|
|
|
|
public function handle()
|
|
|
|
|
{
|
|
|
|
|
$this->startDate = $this->option('start');
|
|
|
|
|
$this->endDate = $this->option('end');
|
|
|
|
|
$configId = $this->option('config-id');
|
|
|
|
|
|
|
|
|
|
// 4. 差异
|
|
|
|
|
$diffCount = $coursesHome['course_count'] - $homeV2['course_periods_total'];
|
|
|
|
|
$this->info("\n--- 差异: 课程数量 courses-home 多 " . $diffCount . " ---");
|
|
|
|
|
if ($configId) {
|
|
|
|
|
$config = CourseTypeDataOverviewConfig::where('status', true)->find($configId);
|
|
|
|
|
if (!$config) {
|
|
|
|
|
$this->error("未找到 status=1 的 config id={$configId}");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
$this->startDate = $config->start_date;
|
|
|
|
|
$this->endDate = $config->end_date ?: date('Y-m-d', strtotime('+10 year'));
|
|
|
|
|
$this->info("使用 config#{$configId} 的日期: {$this->startDate} ~ {$this->endDate}");
|
|
|
|
|
} else {
|
|
|
|
|
$this->info("使用参数日期: {$this->startDate} ~ {$this->endDate}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. 定位多出来的课程来源
|
|
|
|
|
$this->findExtraSources($start, $end, $homeV2, $coursesHome);
|
|
|
|
|
// 1) home-v2 逻辑:按 yearConfigs 的统计方式(只取 is_chart=1 & is_history=0 的 CourseType + 其他)
|
|
|
|
|
$homeV2 = $this->computeHomeV2($this->startDate, $this->endDate);
|
|
|
|
|
// 2) courses-home 逻辑:courseTypesSum 的课程数量、以及涉及的 Course / HistoryCourse
|
|
|
|
|
$coursesHome = $this->computeCoursesHome($this->startDate, $this->endDate);
|
|
|
|
|
|
|
|
|
|
$this->printComparison($homeV2, $coursesHome);
|
|
|
|
|
$this->printDetailDiff($homeV2, $coursesHome);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* home-v2 风格:is_chart=1 且 is_history=0 的 CourseType + 按 name like 的 HistoryCourse + 其他
|
|
|
|
|
* home-v2 的 yearConfigs 统计(单一段 start~end)
|
|
|
|
|
* 返回:期数、去重人数、涉及的 course_ids、history_course_ids
|
|
|
|
|
*/
|
|
|
|
|
protected function computeHomeV2Style(string $start, string $end): array
|
|
|
|
|
protected function computeHomeV2(string $start, string $end): array
|
|
|
|
|
{
|
|
|
|
|
$allCourseTypes = CourseType::where('is_chart', 1)->where('is_history', 0)->orderBy('sort')->get();
|
|
|
|
|
$coursePeriodsTotal = 0;
|
|
|
|
|
$courseSignsUniqueTotal = 0;
|
|
|
|
|
$courseIds = [];
|
|
|
|
|
$historyIds = [];
|
|
|
|
|
$periodsTotal = 0;
|
|
|
|
|
$signsUniqueSum = 0;
|
|
|
|
|
|
|
|
|
|
$dateFilter = function ($q) use ($start, $end) {
|
|
|
|
|
$q->whereBetween('start_date', [$start, $end])->orWhereBetween('end_date', [$start, $end]);
|
|
|
|
|
};
|
|
|
|
|
$historyDateFilter = function ($q) use ($start, $end) {
|
|
|
|
|
$q->whereBetween('start_time', [$start, $end])->orWhereBetween('end_time', [$start, $end]);
|
|
|
|
|
};
|
|
|
|
|
$allCourseTypes = CourseType::where('is_chart', 1)->where('is_history', 0)->orderBy('sort')->get();
|
|
|
|
|
|
|
|
|
|
foreach ($allCourseTypes as $ct) {
|
|
|
|
|
$historyCourse = HistoryCourse::whereHas('typeDetail', fn($q) => $q->where('name', 'like', '%' . $ct->name . '%'))
|
|
|
|
|
->where($historyDateFilter)->get();
|
|
|
|
|
$courses = Course::where('type', $ct->id)->where('is_chart', 1)->where($dateFilter)->get();
|
|
|
|
|
// 历史:typeDetail name like,且仅 type 为 is_history=0(is_history=1 的由下方与 courses-home 口径一致的块统计)
|
|
|
|
|
$history = HistoryCourse::whereHas('typeDetail', function ($q) use ($ct) {
|
|
|
|
|
$q->where('name', 'like', '%' . $ct->name . '%')->where('is_history', 0);
|
|
|
|
|
})->where(function ($q) use ($start, $end) {
|
|
|
|
|
$q->whereBetween('start_time', [$start, $end])
|
|
|
|
|
->orWhereBetween('end_time', [$start, $end]);
|
|
|
|
|
})->get();
|
|
|
|
|
foreach ($history as $h) {
|
|
|
|
|
$historyIds[] = $h->id;
|
|
|
|
|
}
|
|
|
|
|
$historyPeriods = $history->count();
|
|
|
|
|
|
|
|
|
|
// 现在:Course type=$ct->id, is_chart=1
|
|
|
|
|
$courses = Course::where('type', $ct->id)->where('is_chart', 1)
|
|
|
|
|
->where(function ($q) use ($start, $end) {
|
|
|
|
|
$q->whereBetween('start_date', [$start, $end])
|
|
|
|
|
->orWhereBetween('end_date', [$start, $end]);
|
|
|
|
|
})->get();
|
|
|
|
|
foreach ($courses as $c) {
|
|
|
|
|
$courseIds[] = $c->id;
|
|
|
|
|
}
|
|
|
|
|
$nowPeriods = $courses->count();
|
|
|
|
|
|
|
|
|
|
$coursePeriodsTotal += $historyCourse->count() + $courses->count();
|
|
|
|
|
$courseSignsUniqueTotal += $historyCourse->sum('course_type_signs_pass_unique')
|
|
|
|
|
+ (int)CourseSign::courseSignsTotalByUnique($start, $end, 1, $courses->pluck('id'), false, false);
|
|
|
|
|
$periodsTotal += $historyPeriods + $nowPeriods;
|
|
|
|
|
$signsUniqueSum += $history->sum('course_type_signs_pass_unique')
|
|
|
|
|
+ CourseSign::courseSignsTotalByUnique($start, $end, 1, $courses->pluck('id'), false, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$other = CourseType::getOtherStatistics($start, $end);
|
|
|
|
|
$coursePeriodsTotal += $other->course_periods_total;
|
|
|
|
|
$courseSignsUniqueTotal += $other->course_signs_total;
|
|
|
|
|
// 其他 is_chart=0
|
|
|
|
|
$other = CourseType::getOtherStatistics($start, $end);
|
|
|
|
|
$oIds = CourseType::getOtherCourseIds($start, $end);
|
|
|
|
|
$otherH = HistoryCourse::whereIn('type', CourseType::where('is_chart', 0)->where('is_history', 0)->pluck('id'))
|
|
|
|
|
->where(function ($q) use ($start, $end) {
|
|
|
|
|
$q->whereBetween('start_time', [$start, $end])->orWhereBetween('end_time', [$start, $end]);
|
|
|
|
|
})->get();
|
|
|
|
|
foreach ($otherH as $h) {
|
|
|
|
|
$historyIds[] = $h->id;
|
|
|
|
|
}
|
|
|
|
|
foreach (Course::whereIn('id', $oIds)->get() as $c) {
|
|
|
|
|
$courseIds[] = $c->id;
|
|
|
|
|
}
|
|
|
|
|
$periodsTotal += $other->course_periods_total;
|
|
|
|
|
$signsUniqueSum += $other->course_signs_total;
|
|
|
|
|
// getOtherStatistics 内部已含 history,此处仅补 course ids(getOtherCourseIds 与 getOtherStatistics 的 Course 条件一致)
|
|
|
|
|
|
|
|
|
|
return ['course_periods_total' => $coursePeriodsTotal, 'course_signs_unique_total' => $courseSignsUniqueTotal];
|
|
|
|
|
// 与 courses-home 口径一致:附加 is_history=1 的 HistoryCourse(whereHas calendar is_count_people=1,type=体系 id)
|
|
|
|
|
$courseTypesHistory = CourseType::where('is_history', 1)->get();
|
|
|
|
|
foreach ($courseTypesHistory as $hc) {
|
|
|
|
|
$historyList = HistoryCourse::whereHas('calendar', fn ($q) => $q->where('is_count_people', 1))
|
|
|
|
|
->where(fn ($q) => $q->whereBetween('start_time', [$start, $end])->orWhereBetween('end_time', [$start, $end]))
|
|
|
|
|
->where('type', $hc->id)
|
|
|
|
|
->get();
|
|
|
|
|
foreach ($historyList as $h) {
|
|
|
|
|
$historyIds[] = $h->id;
|
|
|
|
|
}
|
|
|
|
|
$periodsTotal += $historyList->count();
|
|
|
|
|
$signsUniqueSum += $historyList->sum('course_type_signs_pass_unique');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
'periods_total' => $periodsTotal,
|
|
|
|
|
'signs_unique_sum' => $signsUniqueSum,
|
|
|
|
|
'course_ids' => array_values(array_unique($courseIds)),
|
|
|
|
|
'history_ids' => array_values(array_unique($historyIds)),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* courses-home 风格:全部 CourseType(含 is_history=1)的 Course(is_chart=1) + is_history=1 的 HistoryCourse(calendar.is_count_people=1)
|
|
|
|
|
* courses-home 的 courseTypesSum:按行展开的课程数量、去重(按类型聚合的那列会重复,这里只算 课程数量/期数)
|
|
|
|
|
* 返回:课程数量(行数)、涉及的 course_ids、history_course_ids
|
|
|
|
|
*/
|
|
|
|
|
protected function computeCoursesHomeStyle(string $start, string $end): array
|
|
|
|
|
protected function computeCoursesHome(string $start, string $end): array
|
|
|
|
|
{
|
|
|
|
|
$course_type_id = CourseType::pluck('id')->toArray();
|
|
|
|
|
$courseTypesSum = [];
|
|
|
|
|
$allCourseIdsForUnique = [];
|
|
|
|
|
|
|
|
|
|
$dateFilter = function ($q) use ($start, $end) {
|
|
|
|
|
if ($start && $end) {
|
|
|
|
|
$q->whereBetween('start_date', [$start, $end])->orWhereBetween('end_date', [$start, $end]);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
$courseIds = [];
|
|
|
|
|
$historyIds = [];
|
|
|
|
|
$courseTypes = CourseType::whereIn('id', CourseType::pluck('id')->toArray())->get();
|
|
|
|
|
|
|
|
|
|
// 第一循环:所有 CourseType(含 is_history=1)
|
|
|
|
|
$courseTypes = CourseType::whereIn('id', $course_type_id)->get();
|
|
|
|
|
// 第一段:非历史 CourseType 下的 Course
|
|
|
|
|
foreach ($courseTypes as $ct) {
|
|
|
|
|
$courses2 = Course::where('type', $ct->id)->where($dateFilter)->where('is_chart', 1)->orderBy('start_date')->get();
|
|
|
|
|
$courses2 = Course::where('type', $ct->id)
|
|
|
|
|
->where(function ($q) use ($start, $end) {
|
|
|
|
|
if ($start && $end) {
|
|
|
|
|
$q->whereBetween('start_date', [$start, $end])
|
|
|
|
|
->orWhereBetween('end_date', [$start, $end]);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
->where('is_chart', 1)
|
|
|
|
|
->orderBy('start_date')
|
|
|
|
|
->get();
|
|
|
|
|
foreach ($courses2 as $c) {
|
|
|
|
|
$courseTypesSum[] = ['source' => 'Course', 'course_type_id' => $ct->id, 'course_type_name' => $ct->name, 'is_history' => $ct->is_history ?? 0, 'course_id' => $c->id, 'course_name' => $c->name];
|
|
|
|
|
$allCourseIdsForUnique[] = $c->id;
|
|
|
|
|
$courseIds[] = $c->id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第二循环:is_history=1 的 HistoryCourse(与 home-v2 一致:仅 typeDetail.name 能匹配某个 is_chart=1 且 is_history=0 的 name)
|
|
|
|
|
$chartHistoryTypeNames = CourseType::where('is_chart', 1)->where('is_history', 0)->pluck('name')->toArray();
|
|
|
|
|
$courseTypesHistory = CourseType::where('is_history', 1)->whereIn('id', $course_type_id)->get();
|
|
|
|
|
$historySignsTotal = 0;
|
|
|
|
|
// 第二段:is_history=1 的 HistoryCourse(与 courses-home 一致:whereHas calendar is_count_people=1)
|
|
|
|
|
$courseTypesHistory = CourseType::where('is_history', 1)->whereIn('id', CourseType::pluck('id')->toArray())->get();
|
|
|
|
|
foreach ($courseTypesHistory as $hc) {
|
|
|
|
|
$historyQ = HistoryCourse::whereHas('calendar', fn($q) => $q->where('is_count_people', 1))
|
|
|
|
|
->where(fn($q) => $q->whereBetween('start_time', [$start, $end])->orWhereBetween('end_time', [$start, $end]))
|
|
|
|
|
->where('type', $hc->id);
|
|
|
|
|
if (!empty($chartHistoryTypeNames)) {
|
|
|
|
|
$historyQ->whereHas('typeDetail', function ($query) use ($chartHistoryTypeNames) {
|
|
|
|
|
$query->where(function ($q2) use ($chartHistoryTypeNames) {
|
|
|
|
|
foreach ($chartHistoryTypeNames as $n) {
|
|
|
|
|
$q2->orWhere('name', 'like', '%' . $n . '%');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
$historyQ->whereHas('typeDetail', fn($query) => $query->whereRaw('1=0'));
|
|
|
|
|
}
|
|
|
|
|
$courses3 = $historyQ->get();
|
|
|
|
|
foreach ($courses3 as $c) {
|
|
|
|
|
$courseTypesSum[] = ['source' => 'HistoryCourse', 'course_type_id' => $hc->id, 'course_type_name' => $hc->name, 'is_history' => 1, 'history_course_id' => $c->id, 'course_name' => $c->course_name];
|
|
|
|
|
$historySignsTotal += (int)($c->course_type_signs_pass_unique ?? 0);
|
|
|
|
|
$courses3 = HistoryCourse::whereHas('calendar', function ($q) {
|
|
|
|
|
$q->where('is_count_people', 1);
|
|
|
|
|
})
|
|
|
|
|
->where(function ($q) use ($start, $end) {
|
|
|
|
|
$q->whereBetween('start_time', [$start, $end])
|
|
|
|
|
->orWhereBetween('end_time', [$start, $end]);
|
|
|
|
|
})
|
|
|
|
|
->where('type', $hc->id)
|
|
|
|
|
->get();
|
|
|
|
|
foreach ($courses3 as $h) {
|
|
|
|
|
$historyIds[] = $h->id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$courseSignsUniqueTotal = (int)CourseSign::courseSignsTotalByUnique($start, $end, 1, $allCourseIdsForUnique ?: [], false, false) + $historySignsTotal;
|
|
|
|
|
// 期数 = courseTypesSum 行数:每个 Course 一行,每个 HistoryCourse 一行
|
|
|
|
|
$periodsTotal = count($courseIds) + count($historyIds);
|
|
|
|
|
|
|
|
|
|
// 去重人数:用与 home-v2 同口径的「所有在 courseTypesSum 里的 course_id + history 对应类型」来算较复杂,
|
|
|
|
|
// 这里仅用 courses-home 实际用到的 Course 的 id 做 courseSignsTotalByUnique,历史用 sum(course_type_signs_pass_unique)
|
|
|
|
|
$allCids = array_values(array_unique($courseIds));
|
|
|
|
|
$signsFromCourse = $allCids
|
|
|
|
|
? (int) CourseSign::courseSignsTotalByUnique($start, $end, 1, $allCids, false, false)
|
|
|
|
|
: 0;
|
|
|
|
|
$signsFromHistory = 0;
|
|
|
|
|
foreach ($courseTypesHistory as $hc) {
|
|
|
|
|
$list = HistoryCourse::whereHas('calendar', fn($q) => $q->where('is_count_people', 1))
|
|
|
|
|
->where(fn($q) => $q->whereBetween('start_time', [$start, $end])->orWhereBetween('end_time', [$start, $end]))
|
|
|
|
|
->where('type', $hc->id)
|
|
|
|
|
->get();
|
|
|
|
|
$signsFromHistory += $list->sum('course_type_signs_pass_unique');
|
|
|
|
|
}
|
|
|
|
|
$signsUniqueSum = $signsFromCourse + $signsFromHistory;
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
'course_count' => count($courseTypesSum),
|
|
|
|
|
'course_signs_unique_total' => $courseSignsUniqueTotal,
|
|
|
|
|
'rows' => $courseTypesSum,
|
|
|
|
|
'periods_total' => $periodsTotal,
|
|
|
|
|
'signs_unique_sum' => $signsUniqueSum,
|
|
|
|
|
'course_ids' => array_values(array_unique($courseIds)),
|
|
|
|
|
'history_ids' => array_values(array_unique($historyIds)),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 找出 courses-home 多出来的课程来源
|
|
|
|
|
*/
|
|
|
|
|
protected function findExtraSources(string $start, string $end, array $homeV2, array $coursesHome): void
|
|
|
|
|
protected function printComparison(array $homeV2, array $coursesHome): void
|
|
|
|
|
{
|
|
|
|
|
$allCourseTypes = CourseType::where('is_chart', 1)->where('is_history', 0)->pluck('id')->toArray();
|
|
|
|
|
$historyDateFilter = function ($q) use ($start, $end) {
|
|
|
|
|
$q->whereBetween('start_time', [$start, $end])->orWhereBetween('end_time', [$start, $end]);
|
|
|
|
|
};
|
|
|
|
|
$dateFilter = function ($q) use ($start, $end) {
|
|
|
|
|
$q->whereBetween('start_date', [$start, $end])->orWhereBetween('end_date', [$start, $end]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// home-v2 会计入的:1) Course: type in is_history=0, is_chart=1, 日期 2) HistoryCourse: typeDetail.name like (is_history=0 的 name), 日期 3) 其他
|
|
|
|
|
$homeV2CourseIds = [];
|
|
|
|
|
foreach (CourseType::where('is_chart', 1)->where('is_history', 0)->get() as $ct) {
|
|
|
|
|
$ids = Course::where('type', $ct->id)->where('is_chart', 1)->where($dateFilter)->pluck('id')->toArray();
|
|
|
|
|
$homeV2CourseIds = array_merge($homeV2CourseIds, $ids);
|
|
|
|
|
}
|
|
|
|
|
$otherCourseIds = Course::whereIn('type', CourseType::where('is_chart', 0)->where('is_history', 0)->pluck('id'))
|
|
|
|
|
->where('is_chart', 1)->where($dateFilter)->pluck('id')->toArray();
|
|
|
|
|
$homeV2CourseIds = array_unique(array_merge($homeV2CourseIds, $otherCourseIds));
|
|
|
|
|
|
|
|
|
|
$homeV2HistoryIds = [];
|
|
|
|
|
foreach (CourseType::where('is_chart', 1)->where('is_history', 0)->get() as $ct) {
|
|
|
|
|
$ids = HistoryCourse::whereHas('typeDetail', fn($q) => $q->where('name', 'like', '%' . $ct->name . '%'))
|
|
|
|
|
->where($historyDateFilter)->pluck('id')->toArray();
|
|
|
|
|
$homeV2HistoryIds = array_merge($homeV2HistoryIds, $ids);
|
|
|
|
|
$this->line('');
|
|
|
|
|
$this->line('========== 汇总对比 ==========');
|
|
|
|
|
$this->table(
|
|
|
|
|
['指标', 'home-v2 (yearConfigs)', 'courses-home (courseTypesSum)', '差异 (courses-home - home-v2)'],
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'期数/课程数量',
|
|
|
|
|
$homeV2['periods_total'],
|
|
|
|
|
$coursesHome['periods_total'],
|
|
|
|
|
$coursesHome['periods_total'] - $homeV2['periods_total'],
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'去重培养人数',
|
|
|
|
|
$homeV2['signs_unique_sum'],
|
|
|
|
|
$coursesHome['signs_unique_sum'],
|
|
|
|
|
$coursesHome['signs_unique_sum'] - $homeV2['signs_unique_sum'],
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'Course 数',
|
|
|
|
|
count($homeV2['course_ids']),
|
|
|
|
|
count($coursesHome['course_ids']),
|
|
|
|
|
count($coursesHome['course_ids']) - count($homeV2['course_ids']),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'HistoryCourse 数',
|
|
|
|
|
count($homeV2['history_ids']),
|
|
|
|
|
count($coursesHome['history_ids']),
|
|
|
|
|
count($coursesHome['history_ids']) - count($homeV2['history_ids']),
|
|
|
|
|
],
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function printDetailDiff(array $homeV2, array $coursesHome): void
|
|
|
|
|
{
|
|
|
|
|
$this->line('');
|
|
|
|
|
$this->line('========== 明细差异(导致 courses-home 多出 期数 的条目) ==========');
|
|
|
|
|
|
|
|
|
|
$h2C = array_flip($homeV2['course_ids']);
|
|
|
|
|
$chC = array_flip($coursesHome['course_ids']);
|
|
|
|
|
$onlyInChC = array_keys(array_diff_key($chC, $h2C));
|
|
|
|
|
$onlyInH2C = array_keys(array_diff_key($h2C, $chC));
|
|
|
|
|
|
|
|
|
|
$h2H = array_flip($homeV2['history_ids']);
|
|
|
|
|
$chH = array_flip($coursesHome['history_ids']);
|
|
|
|
|
$onlyInChH = array_keys(array_diff_key($chH, $h2H));
|
|
|
|
|
$onlyInH2H = array_keys(array_diff_key($h2H, $chH));
|
|
|
|
|
|
|
|
|
|
if (!empty($onlyInChC)) {
|
|
|
|
|
$this->line('【仅 courses-home 有的 Course(会多算期数)】');
|
|
|
|
|
$rows = Course::whereIn('id', $onlyInChC)->get(['id', 'name', 'type', 'start_date', 'end_date', 'is_chart']);
|
|
|
|
|
$this->table(
|
|
|
|
|
['id', 'name', 'type', 'start_date', 'end_date', 'is_chart'],
|
|
|
|
|
$rows->map(fn($r) => [$r->id, $r->name, $r->type, $r->start_date, $r->end_date, $r->is_chart])->toArray()
|
|
|
|
|
);
|
|
|
|
|
$ctIds = $rows->pluck('type')->unique();
|
|
|
|
|
$cts = CourseType::whereIn('id', $ctIds)->get(['id', 'name', 'is_chart', 'is_history']);
|
|
|
|
|
$this->line('对应 CourseType: ' . $cts->map(fn($t) => "id={$t->id} name={$t->name} is_chart={$t->is_chart} is_history={$t->is_history}")->implode('; '));
|
|
|
|
|
}
|
|
|
|
|
$otherHistory = HistoryCourse::whereIn('type', CourseType::where('is_chart', 0)->where('is_history', 0)->pluck('id'))
|
|
|
|
|
->where($historyDateFilter)->pluck('id')->toArray();
|
|
|
|
|
$homeV2HistoryIds = array_unique(array_merge($homeV2HistoryIds, $otherHistory));
|
|
|
|
|
|
|
|
|
|
// courses-home 多出的:在 rows 里但不在 home-v2 的
|
|
|
|
|
$extras = [];
|
|
|
|
|
foreach ($coursesHome['rows'] as $r) {
|
|
|
|
|
if ($r['source'] === 'Course') {
|
|
|
|
|
if (!in_array($r['course_id'], $homeV2CourseIds)) {
|
|
|
|
|
$extras[] = $r;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!in_array($r['history_course_id'], $homeV2HistoryIds)) {
|
|
|
|
|
$extras[] = $r;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!empty($onlyInChH)) {
|
|
|
|
|
$this->line('【仅 courses-home 有的 HistoryCourse(会多算期数)】');
|
|
|
|
|
$rows = HistoryCourse::whereIn('id', $onlyInChH)->get(['id', 'course_name', 'type', 'start_time', 'end_time', 'calendar_id']);
|
|
|
|
|
$this->table(
|
|
|
|
|
['id', 'course_name', 'type', 'start_time', 'end_time', 'calendar_id'],
|
|
|
|
|
$rows->map(fn($r) => [$r->id, $r->course_name, $r->type, $r->start_time, $r->end_time, $r->calendar_id])->toArray()
|
|
|
|
|
);
|
|
|
|
|
$ctIds = $rows->pluck('type')->unique();
|
|
|
|
|
$cts = CourseType::whereIn('id', $ctIds)->get(['id', 'name', 'is_chart', 'is_history']);
|
|
|
|
|
$this->line('对应 CourseType: ' . $cts->map(fn($t) => "id={$t->id} name={$t->name} is_chart={$t->is_chart} is_history={$t->is_history}")->implode('; '));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->info("\n【多出的课程/期(courses-home 有、home-v2 无)】共 " . count($extras) . " 条:");
|
|
|
|
|
foreach ($extras as $e) {
|
|
|
|
|
$this->line(sprintf(
|
|
|
|
|
" - %s | type_id=%s is_history=%s | %s | %s",
|
|
|
|
|
$e['source'],
|
|
|
|
|
$e['course_type_id'],
|
|
|
|
|
$e['is_history'],
|
|
|
|
|
$e['course_name'] ?? '-',
|
|
|
|
|
isset($e['course_id']) ? "course_id={$e['course_id']}" : "history_id={$e['history_course_id']}"
|
|
|
|
|
));
|
|
|
|
|
if (!empty($onlyInH2C)) {
|
|
|
|
|
$this->line('【仅 home-v2 有的 Course】');
|
|
|
|
|
$this->line(implode(', ', $onlyInH2C));
|
|
|
|
|
}
|
|
|
|
|
if (!empty($onlyInH2H)) {
|
|
|
|
|
$this->line('【仅 home-v2 有的 HistoryCourse】');
|
|
|
|
|
$this->line(implode(', ', $onlyInH2H));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 单独列出:type 属于 is_history=1 的 Course(home-v2 不统计此类)
|
|
|
|
|
$isHistory1TypeIds = CourseType::where('is_history', 1)->pluck('id')->toArray();
|
|
|
|
|
$courseFromHistory1Type = Course::whereIn('type', $isHistory1TypeIds)
|
|
|
|
|
->where('is_chart', 1)
|
|
|
|
|
->where($dateFilter)
|
|
|
|
|
->get();
|
|
|
|
|
if ($courseFromHistory1Type->isNotEmpty()) {
|
|
|
|
|
$this->info("\n【属于 is_history=1 课程类型的 Course(home-v2 不统计)】共 " . $courseFromHistory1Type->count() . " 条:");
|
|
|
|
|
foreach ($courseFromHistory1Type as $c) {
|
|
|
|
|
$ct = CourseType::find($c->type);
|
|
|
|
|
$this->line(" - course_id={$c->id} type={$c->type} ({$ct->name}) | {$c->name} | {$c->start_date}~{$c->end_date}");
|
|
|
|
|
}
|
|
|
|
|
if (empty($onlyInChC) && empty($onlyInChH) && empty($onlyInH2C) && empty($onlyInH2H)) {
|
|
|
|
|
$this->line('(无 ID 集合差异;若期数仍不一致,可能是同一条目在两个口径下 算/不算 的规则不同,例如 is_chart、is_count_people、日期区间、type 与 name 匹配等)');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|