validate([ 'ticket_code' => ['required', 'string', 'max:512'], 'audience_session_id' => ['nullable', 'integer', 'min:1'], ], [], [ 'ticket_code' => '入场码', 'audience_session_id' => '场次', ]); $admin = PortalAccess::actor($request); $expectedSessionId = isset($data['audience_session_id']) ? (int) $data['audience_session_id'] : null; if ($expectedSessionId === 0) { $expectedSessionId = null; } $payload = $service->checkInByTicket( $competition, (string) $data['ticket_code'], $admin, $expectedSessionId, ); return response()->json($payload); } public function storeByRegistration( Request $request, Competition $competition, AudienceRegistration $audience_registration, AudienceCheckinService $service, ): JsonResponse { if ((int) $audience_registration->competition_id !== (int) $competition->id) { abort(404); } $admin = PortalAccess::actor($request); $payload = $service->checkInByRegistration($competition, (int) $audience_registration->id, $admin); return response()->json($payload); } public function stats(Request $request, Competition $competition): JsonResponse { $data = $request->validate([ 'audience_session_id' => ['sometimes', 'nullable', 'integer', 'min:1'], ]); $sessionId = (int) ($data['audience_session_id'] ?? 0); $todayStart = Carbon::now(BizDateTime::TIMEZONE)->startOfDay()->utc(); $todayEnd = Carbon::now(BizDateTime::TIMEZONE)->endOfDay()->utc(); $sessions = $competition->audienceSessions() ->withCount([ 'registrations', 'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'), 'registrations as today_checked_in_count' => fn ($q) => $q ->whereNotNull('checked_in_at') ->whereBetween('checked_in_at', [$todayStart, $todayEnd]), ]) ->when($sessionId > 0, fn ($q) => $q->whereKey($sessionId)) ->orderBy('sort') ->orderBy('id') ->get() ->map(function (AudienceSession $session) { $registered = $session->registeredCount(); $checkedIn = $session->checkedInCount(); $todayChecked = (int) ($session->today_checked_in_count ?? 0); return [ 'audience_session_id' => $session->id, 'session_name' => $session->name, 'registered_count' => $registered, 'checked_in_count' => $checkedIn, 'not_checked_in_count' => max(0, $registered - $checkedIn), 'today_checked_in_count' => $todayChecked, 'checkin_rate' => $registered > 0 ? round($checkedIn / $registered, 4) : 0, ]; }); $registered = (int) $sessions->sum('registered_count'); $checkedIn = (int) $sessions->sum('checked_in_count'); $todayChecked = (int) $sessions->sum('today_checked_in_count'); return response()->json([ 'registered_count' => $registered, 'checked_in_count' => $checkedIn, 'not_checked_in_count' => max(0, $registered - $checkedIn), 'today_checked_in_count' => $todayChecked, 'checkin_rate' => $registered > 0 ? round($checkedIn / $registered, 4) : 0, 'sessions' => $sessions->values(), ]); } }