audienceSessions() ->withCount([ 'registrations', 'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'), ]) ->orderBy('sort') ->orderBy('id') ->get() ->map(fn (AudienceSession $session) => $this->toArray($session)); return response()->json(['data' => $sessions]); } public function store(StoreAudienceSessionRequest $request, Competition $competition): JsonResponse { /** @var array $validated */ $validated = $request->validated(); $session = $competition->audienceSessions()->create($validated); $session->loadCount([ 'registrations', 'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'), ]); return response()->json($this->toArray($session), 201); } public function show(Competition $competition, AudienceSession $audience_session): JsonResponse { $this->ensureBelongs($competition, $audience_session); $audience_session->loadCount([ 'registrations', 'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'), ]); return response()->json($this->toArray($audience_session)); } public function update( UpdateAudienceSessionRequest $request, Competition $competition, AudienceSession $audience_session, ): JsonResponse { $this->ensureBelongs($competition, $audience_session); /** @var array $validated */ $validated = $request->validated(); if (array_key_exists('capacity', $validated)) { $registered = $audience_session->registeredCount(); if ((int) $validated['capacity'] < $registered) { throw ValidationException::withMessages([ 'capacity' => ['容量不能小于已报名人数('.$registered.')'], ]); } } $audience_session->fill($validated); $audience_session->save(); $audience_session->loadCount([ 'registrations', 'registrations as checked_in_count' => fn ($q) => $q->whereNotNull('checked_in_at'), ]); return response()->json($this->toArray($audience_session)); } public function destroy(Competition $competition, AudienceSession $audience_session): Response { $this->ensureBelongs($competition, $audience_session); if ($audience_session->registrations()->exists()) { throw ValidationException::withMessages([ 'audience_session' => ['该场次已有报名记录,请停用而不是删除'], ]); } $audience_session->delete(); return response()->noContent(); } /** * @return array */ private function toArray(AudienceSession $session): array { return [ 'id' => $session->id, 'competition_id' => $session->competition_id, 'code' => $session->code, 'name' => $session->name, 'event_date_text' => $session->event_date_text, 'address' => $session->address, 'capacity' => (int) $session->capacity, 'registered_count' => $session->registeredCount(), 'checked_in_count' => $session->checkedInCount(), 'remaining' => $session->remainingCount(), 'signup_start_at' => BizDateTime::toIso8601($session->signup_start_at), 'signup_end_at' => BizDateTime::toIso8601($session->signup_end_at), 'is_final' => (bool) $session->is_final, 'sort' => (int) $session->sort, 'enabled' => (bool) $session->enabled, 'status' => $session->windowStatus(), 'status_label' => $session->statusLabel(), 'created_at' => BizDateTime::toIso8601($session->created_at), 'updated_at' => BizDateTime::toIso8601($session->updated_at), ]; } private function ensureBelongs(Competition $competition, AudienceSession $session): void { if ((int) $session->competition_id !== (int) $competition->id) { abort(404); } } }