lotteryAdmin(); abort_if($admin === null, 401); $p = AdminApiList::readPaging($request); $drawNo = trim((string) $request->query('draw_no', '')); $status = trim((string) $request->query('status', '')); $scope = AdminScopePolicy::resolveContext($request, $admin); $q = Draw::query()->orderByDesc('draw_time')->orderByDesc('id'); if ($drawNo !== '') { $q->where('draw_no', 'like', '%'.$drawNo.'%'); } if ($status !== '') { $q->where('status', $status); } /** @var LengthAwarePaginator $paginator */ $paginator = $q->paginate($p['perPage'], ['*'], 'page', $p['page']); $statsByDrawId = AdminDrawResponsePolicy::canViewDrawFinance($admin) ? $this->aggregateListStats( $paginator->getCollection()->pluck('id')->map(fn ($id) => (int) $id)->all(), $scope, ) : []; return AdminApiList::jsonWith( $paginator, fn (Draw $row): array => AdminDrawApiPresenter::listRow( $row, $statsByDrawId[(int) $row->id] ?? null, $admin, ), [ 'schedule' => [ 'timezone' => LotterySettings::drawTimezone(), 'interval_minutes' => LotterySettings::drawIntervalMinutes(), 'betting_window_seconds' => LotterySettings::drawBettingWindowSeconds(), 'close_before_draw_seconds' => LotterySettings::drawCloseBeforeDrawSeconds(), ], 'capabilities' => AdminDrawResponsePolicy::capabilities($admin), ], ); } /** * @param list $drawIds * @return array */ private function aggregateListStats(array $drawIds, AdminScopeContext $scope): array { if ($drawIds === []) { return []; } $betQuery = TicketOrder::query()->whereIn('draw_id', $drawIds); $this->scopeOrdersToVisiblePlayers($betQuery, $scope); $betByDraw = $betQuery ->groupBy('draw_id') ->selectRaw('draw_id, COALESCE(SUM(total_actual_deduct), 0) AS total_bet') ->pluck('total_bet', 'draw_id'); $payoutQuery = TicketItem::query()->whereIn('draw_id', $drawIds); $this->scopeTicketItemsToVisiblePlayers($payoutQuery, $scope); $payoutRows = $payoutQuery ->groupBy('draw_id') ->selectRaw( 'draw_id, COALESCE(SUM(win_amount), 0) AS win, COALESCE(SUM(jackpot_win_amount), 0) AS jackpot', ) ->get() ->keyBy('draw_id'); $stats = []; foreach ($drawIds as $drawId) { $bet = (int) ($betByDraw[$drawId] ?? $betByDraw[(string) $drawId] ?? 0); $payoutRow = $payoutRows->get($drawId) ?? $payoutRows->get((string) $drawId); $payout = (int) ($payoutRow->win ?? 0) + (int) ($payoutRow->jackpot ?? 0); $stats[$drawId] = [ 'total_bet_minor' => $bet, 'total_payout_minor' => $payout, 'profit_loss_minor' => $bet - $payout, ]; } return $stats; } /** * @param \Illuminate\Database\Eloquent\Builder $query */ private function scopeOrdersToVisiblePlayers($query, AdminScopeContext $scope): void { if ($scope->isSuperAdmin() && $scope->effectiveRequestedAgentNodeId() === null) { return; } $query->whereHas('player', function ($playerQuery) use ($scope): void { AdminScopePolicy::applyPlayerFilters($playerQuery, $scope); }); } /** * @param \Illuminate\Database\Eloquent\Builder $query */ private function scopeTicketItemsToVisiblePlayers($query, AdminScopeContext $scope): void { if ($scope->isSuperAdmin() && $scope->effectiveRequestedAgentNodeId() === null) { return; } $query->whereHas('player', function ($playerQuery) use ($scope): void { AdminScopePolicy::applyPlayerFilters($playerQuery, $scope); }); } }