lotteryPlayer(); abort_if($player === null, 500, 'lottery_player missing'); if (! PlayerFundingMode::usesCredit($player)) { return ApiResponse::success([ 'items' => [], 'summary' => [ 'pending_receivable' => 0, 'pending_payable' => 0, 'net_pending' => 0, 'pending_count' => 0, ], 'funding_mode' => (string) ($player->funding_mode ?? PlayerFundingMode::WALLET), ]); } $rows = DB::table('settlement_bills as sb') ->join('settlement_periods as sp', 'sp.id', '=', 'sb.settlement_period_id') ->where('sb.bill_type', 'player') ->where('sb.owner_type', 'player') ->where('sb.owner_id', (int) $player->id) ->whereIn('sb.status', ['pending_confirm', 'confirmed', 'partial_paid', 'overdue']) ->orderByDesc('sp.period_end') ->orderByDesc('sb.id') ->limit(5) ->get([ 'sb.id', 'sb.settlement_period_id', 'sb.gross_win_loss', 'sb.rebate_amount', 'sb.net_amount', 'sb.paid_amount', 'sb.unpaid_amount', 'sb.status', 'sp.period_start', 'sp.period_end', ]); $pendingReceivable = 0; $pendingPayable = 0; $items = $rows->map(function (object $row) use (&$pendingReceivable, &$pendingPayable): array { $netAmount = (int) $row->net_amount; $unpaidAmount = (int) $row->unpaid_amount; $direction = $netAmount > 0 ? 'payable' : 'receivable'; if ($direction === 'payable') { $pendingPayable += $unpaidAmount; } else { $pendingReceivable += $unpaidAmount; } return [ 'id' => (int) $row->id, 'settlement_period_id' => (int) $row->settlement_period_id, 'period_start' => $this->isoTimestamp($row->period_start), 'period_end' => $this->isoTimestamp($row->period_end), 'gross_win_loss' => (int) $row->gross_win_loss, 'rebate_amount' => (int) $row->rebate_amount, 'net_amount' => $netAmount, 'paid_amount' => (int) $row->paid_amount, 'unpaid_amount' => $unpaidAmount, 'direction' => $direction, 'status' => (string) $row->status, ]; })->all(); return ApiResponse::success([ 'items' => $items, 'summary' => [ 'pending_receivable' => $pendingReceivable, 'pending_receivable_formatted' => CurrencyFormatter::fromMinor($pendingReceivable), 'pending_payable' => $pendingPayable, 'pending_payable_formatted' => CurrencyFormatter::fromMinor($pendingPayable), 'net_pending' => $pendingReceivable - $pendingPayable, 'net_pending_formatted' => CurrencyFormatter::fromMinor(abs($pendingReceivable - $pendingPayable)), 'pending_count' => count($items), ], 'funding_mode' => PlayerFundingMode::CREDIT, ]); } private function isoTimestamp(mixed $value): ?string { if ($value === null || $value === '') { return null; } return \Carbon\Carbon::parse((string) $value)->toIso8601String(); } }