|
|
<?php
|
|
|
|
|
|
namespace App\Http\Controllers\Api\Admin;
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
use App\Http\Requests\Admin\StoreAudienceSessionRequest;
|
|
|
use App\Http\Requests\Admin\UpdateAudienceSessionRequest;
|
|
|
use App\Models\AudienceSession;
|
|
|
use App\Models\Competition;
|
|
|
use App\Support\BizDateTime;
|
|
|
use Illuminate\Http\JsonResponse;
|
|
|
use Illuminate\Http\Response;
|
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
|
|
class AudienceSessionController extends Controller
|
|
|
{
|
|
|
public function index(Competition $competition): JsonResponse
|
|
|
{
|
|
|
$sessions = $competition->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<string, mixed> $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<string, mixed> $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<string, mixed>
|
|
|
*/
|
|
|
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);
|
|
|
}
|
|
|
}
|
|
|
}
|