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
154 lines
5.2 KiB
|
2 weeks ago
|
<?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(),
|
||
|
|
];
|
||
|
|
}
|
||
|
|
}
|