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.

154 lines
5.2 KiB

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Course;
use App\Models\CourseSignup;
use App\Models\CourseSignupCheckin;
use App\Support\ApiResponse;
use App\Support\CourseCheckinDaySync;
use App\Support\SignupFormAnswers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CourseSignupController extends Controller
{
use ApiResponse;
public function index(Request $request, int $course): JsonResponse
{
Course::query()->findOrFail($course);
$checkinDate = $request->query('checkin_date');
$checkinStatus = $request->query('checkin_status');
$query = CourseSignup::query()->where('course_id', $course)->orderByDesc('id');
if ($kw = $request->query('keyword')) {
$query->where(function ($q) use ($kw) {
$q->where('name', 'like', "%{$kw}%")
->orWhere('mobile', 'like', "%{$kw}%")
->orWhere('company', 'like', "%{$kw}%");
});
}
if ($checkinDate) {
if ((string) $checkinStatus === '1') {
$query->whereHas('checkins', function ($q) use ($checkinDate) {
$q->whereDate('checkin_date', $checkinDate)->whereNotNull('checked_in_at');
});
} elseif ((string) $checkinStatus === '0') {
$query->whereDoesntHave('checkins', function ($q) use ($checkinDate) {
$q->whereDate('checkin_date', $checkinDate)->whereNotNull('checked_in_at');
});
}
}
$paginator = $query
->with(['checkins' => function ($q) use ($checkinDate) {
if ($checkinDate) {
$q->whereDate('checkin_date', $checkinDate);
}
}])
->paginate((int) $request->query('page_size', 20))
->withQueryString();
$paginator->getCollection()->transform(
fn (CourseSignup $r) => $this->serialize($r, is_string($checkinDate) ? $checkinDate : null)
);
return $this->paginated($paginator);
}
public function store(Request $request, int $course): JsonResponse
{
$courseModel = Course::query()->findOrFail($course);
$data = $request->validate([
'name' => ['required', 'string', 'max:64'],
'mobile' => ['required', 'string', 'max:32'],
'company' => ['nullable', 'string', 'max:128'],
'form_answers' => ['nullable', 'array'],
]);
$formAnswers = null;
if (isset($data['form_answers']) && is_array($data['form_answers'])) {
$formAnswers = SignupFormAnswers::normalize(
$data['form_answers'],
is_array($courseModel->signup_form_schema) ? $courseModel->signup_form_schema : null
);
}
$signup = CourseSignup::query()->create([
'course_id' => $course,
'name' => $data['name'],
'mobile' => $data['mobile'],
'company' => $data['company'] ?? null,
'form_answers' => $formAnswers,
'signed_up_at' => now(),
'status' => 1,
]);
return $this->ok(['id' => $signup->id], '报名已登记');
}
public function destroy(int $course, int $signup): JsonResponse
{
$model = CourseSignup::query()->where('course_id', $course)->findOrFail($signup);
$model->delete();
return $this->ok(null, '已删除');
}
public function checkin(Request $request, int $course, int $signup): JsonResponse
{
$courseModel = Course::query()->findOrFail($course);
$model = CourseSignup::query()->where('course_id', $course)->findOrFail($signup);
$data = $request->validate([
'checkin_date' => ['required', 'date'],
]);
$checkinDate = $data['checkin_date'];
if (! CourseCheckinDaySync::isTeachDate($courseModel, $checkinDate)) {
return $this->fail('该日期不在课程开课范围内', 422);
}
CourseSignupCheckin::query()->updateOrCreate(
[
'course_signup_id' => $model->id,
'checkin_date' => $checkinDate,
],
['checked_in_at' => now()]
);
return $this->ok(null, '签到成功');
}
/**
* @return array<string, mixed>
*/
protected function serialize(CourseSignup $r, ?string $checkinDate = null): array
{
$dayCheckedInAt = null;
if ($checkinDate) {
$checkin = $r->relationLoaded('checkins')
? $r->checkins->first()
: $r->checkins()->whereDate('checkin_date', $checkinDate)->first();
$dayCheckedInAt = $checkin?->checked_in_at;
}
return [
'id' => $r->id,
'course_id' => $r->course_id,
'name' => $r->name,
'mobile' => $r->mobile,
'company' => $r->company,
'form_answers' => $r->form_answers,
'signed_up_at' => $r->signed_up_at?->toIso8601String(),
'status' => (int) $r->status,
'checkin_date' => $checkinDate,
'day_checked_in_at' => $dayCheckedInAt?->toIso8601String(),
];
}
}