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.
124 lines
3.4 KiB
124 lines
3.4 KiB
|
1 week ago
|
<?php
|
||
|
|
|
||
|
|
namespace App\Support;
|
||
|
|
|
||
|
|
use App\Models\Course;
|
||
|
|
use App\Models\CourseCheckinDay;
|
||
|
|
use Carbon\Carbon;
|
||
|
|
use Carbon\CarbonPeriod;
|
||
|
|
|
||
|
|
class CourseCheckinDaySync
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* @return list<array{id: int, course_id: int, teach_date: string}>
|
||
|
|
*/
|
||
|
|
public static function listTeachDates(Course $course): array
|
||
|
|
{
|
||
|
|
if (! $course->teach_start_date || ! $course->teach_end_date) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
|
||
|
|
$start = $course->teach_start_date->copy()->startOfDay();
|
||
|
|
$end = $course->teach_end_date->copy()->startOfDay();
|
||
|
|
if ($start->gt($end)) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
|
||
|
|
$items = [];
|
||
|
|
$seq = 0;
|
||
|
|
foreach (CarbonPeriod::create($start, $end) as $day) {
|
||
|
|
/** @var Carbon $day */
|
||
|
|
$seq++;
|
||
|
|
$items[] = [
|
||
|
|
'id' => $seq,
|
||
|
|
'course_id' => $course->id,
|
||
|
|
'teach_date' => $day->toDateString(),
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
return $items;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function isTeachDate(Course $course, string $dateYmd): bool
|
||
|
|
{
|
||
|
|
foreach (self::listTeachDates($course) as $item) {
|
||
|
|
if ($item['teach_date'] === $dateYmd) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function syncForCourse(Course $course): void
|
||
|
|
{
|
||
|
|
if (! $course->teach_start_date || ! $course->teach_end_date) {
|
||
|
|
CourseCheckinDay::query()->where('course_id', $course->id)->delete();
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$start = $course->teach_start_date->copy()->startOfDay();
|
||
|
|
$end = $course->teach_end_date->copy()->startOfDay();
|
||
|
|
if ($start->gt($end)) {
|
||
|
|
CourseCheckinDay::query()->where('course_id', $course->id)->delete();
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$period = CarbonPeriod::create($start, $end);
|
||
|
|
$keepDates = [];
|
||
|
|
|
||
|
|
foreach ($period as $day) {
|
||
|
|
/** @var Carbon $day */
|
||
|
|
$dateStr = $day->toDateString();
|
||
|
|
$keepDates[] = $dateStr;
|
||
|
|
|
||
|
|
CourseCheckinDay::query()->updateOrCreate(
|
||
|
|
[
|
||
|
|
'course_id' => $course->id,
|
||
|
|
'teach_date' => $dateStr,
|
||
|
|
],
|
||
|
|
['signin_code' => $course->id.'-'.$dateStr]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
CourseCheckinDay::query()
|
||
|
|
->where('course_id', $course->id)
|
||
|
|
->whereNotIn('teach_date', $keepDates)
|
||
|
|
->delete();
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function courseSigninCode(Course $course): string
|
||
|
|
{
|
||
|
|
if ($course->code) {
|
||
|
|
$base = preg_replace('/[^A-Za-z0-9_-]/', '', $course->code) ?: ('C'.$course->id);
|
||
|
|
|
||
|
|
return strtoupper($base);
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($course->code_prefix) {
|
||
|
|
$base = preg_replace('/[^A-Za-z0-9_-]/', '', $course->code_prefix) ?: ('C'.$course->id);
|
||
|
|
|
||
|
|
return strtoupper($base);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 'COURSE-'.str_pad((string) $course->id, 3, '0', STR_PAD_LEFT);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static function ensureCourseCode(Course $course): void
|
||
|
|
{
|
||
|
|
if ($course->code) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$prefix = $course->code_prefix
|
||
|
|
? preg_replace('/[^A-Za-z0-9_-]/', '', $course->code_prefix)
|
||
|
|
: '';
|
||
|
|
$course->code = $prefix
|
||
|
|
? 'COURSE-'.strtoupper($prefix).'-'.str_pad((string) $course->id, 3, '0', STR_PAD_LEFT)
|
||
|
|
: 'COURSE-'.str_pad((string) $course->id, 3, '0', STR_PAD_LEFT);
|
||
|
|
$course->save();
|
||
|
|
}
|
||
|
|
}
|