create([ 'draw_no' => '20260512-010', 'business_date' => '2026-05-12', 'sequence_no' => 10, 'status' => 'open', 'start_time' => now()->subHour(), 'close_time' => now()->addHour(), 'draw_time' => now()->addHours(2), 'cooling_end_time' => null, 'result_source' => null, 'current_result_version' => 0, 'settle_version' => 0, 'is_reopened' => false, ]); RiskPool::query()->create([ 'draw_id' => $draw->id, 'normalized_number' => '1234', 'total_cap_amount' => 1_000_000, 'locked_amount' => 200_000, 'remaining_amount' => 800_000, 'sold_out_status' => 0, 'version' => 1, ]); RiskPool::query()->create([ 'draw_id' => $draw->id, 'normalized_number' => '9999', 'total_cap_amount' => 100, 'locked_amount' => 100, 'remaining_amount' => 0, 'sold_out_status' => 1, 'version' => 2, ]); $admin = AdminUser::query()->create([ 'username' => 'dash_admin', 'name' => 'Dash QA', 'email' => null, 'password' => Hash::make('secret-strong'), 'status' => 0, ]); grantSuperAdminRole($admin); $token = $admin->createToken('test', ['*'], now()->addDay())->plainTextToken; $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/admin/dashboard') ->assertOk() ->assertJsonPath('data.hall.draw_no', '20260512-010') ->assertJsonPath('data.resolved_draw.id', $draw->id) ->assertJsonPath('data.capabilities.draw_finance_risk', true) ->assertJsonPath('data.capabilities.wallet_transfer_view', true) ->assertJsonPath('data.today_finance.business_date', now()->toDateString()) ->assertJsonPath('data.today_finance.total_bet_minor', 0) ->assertJsonPath('data.finance.draw_id', $draw->id) ->assertJsonPath('data.draw.result_batch_counts.total', 0) ->assertJsonPath('data.risk.locked_amount', 200_100) ->assertJsonPath('data.risk.cap_amount', 1_000_100) ->assertJsonPath('data.risk.sold_out_buckets.d4', 1); }); test('admin dashboard counts pending result batches site wide not only current draw', function (): void { $hallDraw = Draw::query()->create([ 'draw_no' => '20260512-020', 'business_date' => '2026-05-12', 'sequence_no' => 20, 'status' => 'open', 'start_time' => now()->subHour(), 'close_time' => now()->addHour(), 'draw_time' => now()->addHours(2), 'cooling_end_time' => null, 'result_source' => null, 'current_result_version' => 0, 'settle_version' => 0, 'is_reopened' => false, ]); $reviewDraw = Draw::query()->create([ 'draw_no' => '20260512-019', 'business_date' => '2026-05-12', 'sequence_no' => 19, 'status' => DrawStatus::Review->value, 'start_time' => now()->subHours(3), 'close_time' => now()->subHour(), 'draw_time' => now()->subMinutes(30), 'cooling_end_time' => null, 'result_source' => DrawResultSourceType::Manual->value, 'current_result_version' => 0, 'settle_version' => 0, 'is_reopened' => false, ]); DrawResultBatch::query()->create([ 'draw_id' => $reviewDraw->id, 'result_version' => 1, 'source_type' => DrawResultSourceType::Manual->value, 'rng_seed_hash' => null, 'raw_seed_encrypted' => null, 'status' => DrawResultBatchStatus::PendingReview->value, 'created_by' => null, 'confirmed_by' => null, 'confirmed_at' => null, ]); $admin = AdminUser::query()->create([ 'username' => 'dash_queue_admin', 'name' => 'Dash Queue QA', 'email' => null, 'password' => Hash::make('secret-strong'), 'status' => 0, ]); grantSuperAdminRole($admin); $token = $admin->createToken('test', ['*'], now()->addDay())->plainTextToken; $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/v1/admin/dashboard') ->assertOk() ->assertJsonPath('data.resolved_draw.id', $hallDraw->id) ->assertJsonPath('data.draw.result_batch_counts.pending_review', 0) ->assertJsonPath('data.result_batch_queue.pending_review_total', 1) ->assertJsonPath('data.result_batch_queue.pending_draw_count', 1) ->assertJsonPath('data.result_batch_queue.first_pending_draw_id', $reviewDraw->id); }); test('admin dashboard returns 401 without token', function (): void { $this->getJson('/api/v1/admin/dashboard')->assertStatus(401); });