|null */ public function build(AdminUser $admin, AdminScopeContext $scope): ?array { if (! $admin->hasPermissionCode('dashboard.view')) { return null; } $site = SiteDashboardSiteResolver::resolvePrimarySite($admin); if ($site === null) { return null; } $siteId = (int) $site->id; $siteCode = (string) $site->code; $agentNodeIds = AgentNode::query() ->where('admin_site_id', $siteId) ->pluck('id') ->map(static fn ($id): int => (int) $id) ->all(); $playerCount = (int) Player::query()->where('site_code', $siteCode)->count(); $today = now()->toDateString(); $sevenDayFrom = now()->subDays(6)->toDateString(); $scoped = AdminScopeContextResolver::fromValues( $admin, requestedSiteCode: $siteCode, ); $todayTotals = $this->reportQuery->periodFinanceTotals($today, $today, $scoped); $sevenDayTotals = $this->reportQuery->periodFinanceTotals($sevenDayFrom, $today, $scoped); $currencyCode = $this->reportQuery->resolvePeriodCurrencyCode($today, $today, $scoped) ?? $this->reportQuery->resolvePeriodCurrencyCode($sevenDayFrom, $today, $scoped); $todayActivity = $this->todayActivityStats($siteCode, $today); $billStats = SiteSettlementBillStats::forSite($siteId); $pendingBills = [ 'count' => $billStats['pending_confirm_count'] + $billStats['payable_count'], 'unpaid_minor' => $billStats['payable_unpaid_minor'], ]; $topAgentToday = $this->topAgentToday($scoped, $today); return [ 'admin_site_id' => $siteId, 'site_code' => $siteCode, 'site_name' => (string) $site->name, 'agent_count' => count($agentNodeIds), 'player_count' => $playerCount, 'active_player_count_today' => $todayActivity['player_count'], 'bet_order_count_today' => $todayActivity['order_count'], 'today_bet_minor' => $todayTotals['total_bet_minor'], 'today_payout_minor' => $todayTotals['total_payout_minor'], 'today_profit_minor' => $todayTotals['approx_house_gross_minor'], 'seven_day_bet_minor' => $sevenDayTotals['total_bet_minor'], 'seven_day_payout_minor' => $sevenDayTotals['total_payout_minor'], 'seven_day_profit_minor' => $sevenDayTotals['approx_house_gross_minor'], 'profit_scope' => 'house_gross', 'currency_code' => $currencyCode, 'pending_bill_count' => $pendingBills['count'], 'pending_unpaid_minor' => $pendingBills['unpaid_minor'], 'latest_bet_at' => $todayActivity['latest_bet_at'], 'top_agent_today' => $topAgentToday, ]; } /** * @return array{player_count: int, order_count: int, latest_bet_at: ?string} */ private function todayActivityStats(string $siteCode, string $today): array { $base = DB::table('ticket_orders as o') ->join('draws as d', 'd.id', '=', 'o.draw_id') ->join('players as p', 'p.id', '=', 'o.player_id') ->where('p.site_code', $siteCode) ->whereDate('d.business_date', $today); $latestBetAt = (clone $base)->max('o.created_at'); return [ 'player_count' => (int) (clone $base)->distinct('o.player_id')->count('o.player_id'), 'order_count' => (int) (clone $base)->count(), 'latest_bet_at' => $latestBetAt !== null ? Carbon::parse((string) $latestBetAt)->toIso8601String() : null, ]; } /** * @return array|null */ private function topAgentToday(AdminScopeContext $scope, string $today): ?array { $rows = $this->reportQuery->agentRankingRows($today, $today, null, 1, $scope); return $rows[0] ?? null; } }