PHP WebShell

Текущая директория: /var/www/bitcardoApp/backyard/models/dashboard

Просмотр файла: index.php

<?php
// backyard/models/dashboard/index.php
// Pure functions that read from $conn (procedural MySQLi). No side effects.

// If your project globally enables mysqli exceptions, we can catch them below.
// If not, the try/catch is harmless.
function dash_q_scalar(mysqli $conn, string $sql, string $field = 'c', int|float $default = 0) {
    try {
        $res = mysqli_query($conn, $sql);
        if ($res) {
            $row = mysqli_fetch_assoc($res);
            mysqli_free_result($res);
            if ($row && array_key_exists($field, $row)) {
                return is_numeric($row[$field]) ? 0 + $row[$field] : $default;
            }
        }
    } catch (\mysqli_sql_exception $e) {
        // Optionally log error somewhere:
        // error_log('dash_q_scalar error: ' . $e->getMessage());
    }
    return $default;
}

/**
 * Overview metrics for dashboard header.
 * - users_count: total active users
 * - transactions_count: total transactions
 * - today_giftcard_usd: sum of today's gift card trades in USD-like currency (USD or '$')
 * - today_trades_count: number of today's gift card trades
 */
function dash_get_overview(mysqli $conn): array {
    $overview = [
        'users_count'         => 0,
        'transactions_count'  => 0,
        'today_giftcard_usd'  => 0.0,
        'today_trades_count'  => 0,
    ];

    // Users (active)
    $overview['users_count'] = (int) dash_q_scalar(
        $conn,
        "SELECT COUNT(*) AS c FROM `users` WHERE `user_status` = 'Active'"
    );

    // Transactions (all)
    $overview['transactions_count'] = (int) dash_q_scalar(
        $conn,
        "SELECT COUNT(*) AS c FROM `transactions`"
    );

    // Today's gift card trades (USD-like)
    // Keep single-line SQL to avoid hidden characters
    try {
        $sql = "SELECT COALESCE(SUM(card_value),0) AS total_value, COUNT(*) AS trade_count FROM `card_trade` WHERE DATE(`trade_created`) = CURDATE() AND (`card_curr` = 'USD' OR `card_curr` = '$')";
        $res = mysqli_query($conn, $sql);
        if ($res) {
            $row = mysqli_fetch_assoc($res);
            mysqli_free_result($res);
            if ($row) {
                $overview['today_giftcard_usd'] = (float) ($row['total_value'] ?? 0);
                $overview['today_trades_count'] = (int) ($row['trade_count'] ?? 0);
            }
        }
    } catch (\mysqli_sql_exception $e) {
        // error_log('dash_get_overview today USD error: ' . $e->getMessage());
    }

    return $overview;
}

/**
 * Central wallets with aggregated user balances.
 * Returns up to $limit rows with keys:
 * coin, icon, status, platform_balance, user_balance, growth_percent
 */
function dash_get_platform_wallets(mysqli $conn, int $limit = 6): array {
    $wallets = [];

    try {
        $limit = max(1, (int)$limit);
        $sql = "SELECT * FROM `cwallet` ORDER BY `cwallet_id` ASC LIMIT {$limit}";
        $res = mysqli_query($conn, $sql);
        if (!$res) {
            return $wallets;
        }

        while ($w = mysqli_fetch_assoc($res)) {
            $coin             = $w['coin'] ?? '';
            $icon             = $w['icon'] ?? '';
            $status           = $w['status'] ?? '';
            $platform_balance = (float)($w['wallet_balance'] ?? 0);

            // Sum of all users' balances for the same coin
            $coin_safe = mysqli_real_escape_string($conn, (string)$coin);
            $sum_sql   = "SELECT COALESCE(SUM(`balance`),0) AS total_user_balance FROM `user_wallets` WHERE `coin` = '{$coin_safe}'";
            $user_balance = 0.0;

            try {
                $sum_res = mysqli_query($conn, $sum_sql);
                if ($sum_res) {
                    $sum_row = mysqli_fetch_assoc($sum_res);
                    mysqli_free_result($sum_res);
                    if ($sum_row) {
                        $user_balance = (float)($sum_row['total_user_balance'] ?? 0);
                    }
                }
            } catch (\mysqli_sql_exception $e) {
                // error_log('dash_get_platform_wallets sum error: ' . $e->getMessage());
            }

            // Growth: platform vs users
            $growth_percent = 0.0;
            if ($user_balance > 0) {
                $growth_percent = (($platform_balance - $user_balance) / $user_balance) * 100.0;
            }

            $wallets[] = [
                'coin'              => $coin,
                'icon'              => $icon,
                'status'            => $status,
                'platform_balance'  => $platform_balance,
                'user_balance'      => $user_balance,
                'growth_percent'    => $growth_percent,
            ];
        }
        mysqli_free_result($res);
    } catch (\mysqli_sql_exception $e) {
        // error_log('dash_get_platform_wallets error: ' . $e->getMessage());
        return $wallets;
    }

    return $wallets;
}



/**
 * Recent gift card batches (one row per batch_ref).
 * Returns rows:
 * - batch_ref, first_name, last_name, total_payout, cards_count
 * - ok_count, pending_count, bad_count, last_time
 */
function dash_get_recent_giftcard_batches(mysqli $conn, int $limit = 10): array {
    $rows = [];
    $limit = max(1, (int)$limit);

    // Use MAX() to pick a representative name from the batch (safe for ONLY_FULL_GROUP_BY)
    $sql = "
        SELECT
            ct.batch_ref,
            MAX(u.first_name) AS first_name,
            MAX(u.last_name)  AS last_name,
            SUM(ct.est_payout_ngn) AS total_payout,
            COUNT(*) AS cards_count,
            SUM(ct.trade_status IN ('SUCCESS','COMPLETED','APPROVED'))   AS ok_count,
            SUM(ct.trade_status IN ('PENDING','PROCESSING'))             AS pending_count,
            SUM(ct.trade_status IN ('DECLINED','FAILED','REJECTED'))     AS bad_count,
            MAX(ct.trade_created) AS last_time
        FROM card_trade ct
        LEFT JOIN users u ON u.user_id = ct.user_id
        WHERE ct.batch_ref IS NOT NULL AND ct.batch_ref <> ''
        GROUP BY ct.batch_ref
        ORDER BY last_time DESC
        LIMIT {$limit}
    ";

    try {
        if ($res = mysqli_query($conn, $sql)) {
            while ($r = mysqli_fetch_assoc($res)) {
                $rows[] = [
                    'batch_ref'    => $r['batch_ref'] ?? '',
                    'first_name'   => $r['first_name'] ?? '',
                    'last_name'    => $r['last_name'] ?? '',
                    'total_payout' => (float)($r['total_payout'] ?? 0),
                    'cards_count'  => (int)($r['cards_count'] ?? 0),
                    'ok_count'     => (int)($r['ok_count'] ?? 0),
                    'pending_count'=> (int)($r['pending_count'] ?? 0),
                    'bad_count'    => (int)($r['bad_count'] ?? 0),
                    'last_time'    => $r['last_time'] ?? null,
                ];
            }
            mysqli_free_result($res);
        }
    } catch (\mysqli_sql_exception $e) {}

    return $rows;
}

/**
 * Compute a batch status from component counts.
 */
function dash_batch_status(array $b): string {
    $ok = (int)($b['ok_count'] ?? 0);
    $pd = (int)($b['pending_count'] ?? 0);
    $bd = (int)($b['bad_count'] ?? 0);
    $total = (int)($b['cards_count'] ?? 0);

    if ($total > 0 && $ok === $total) return 'Success';
    if ($pd > 0 && $bd === 0)        return 'Pending';
    if ($bd > 0 && $ok === 0 && $pd === 0) return 'Declined';
    if ($bd > 0 && ($ok > 0 || $pd > 0))   return 'Mixed';
    return 'Unknown';
}

/**
 * Batch details + member cards for process_order.php
 * Returns ['batch' => summary, 'cards' => [...]]
 */
function dash_get_batch_details(mysqli $conn, string $batch_ref): array {
    $batch_ref_safe = mysqli_real_escape_string($conn, $batch_ref);
    $out = ['batch' => null, 'cards' => []];

    // Summary
    $sum_sql = "
        SELECT
            ct.batch_ref,
            MAX(u.first_name) AS first_name,
            MAX(u.last_name)  AS last_name,
            SUM(ct.est_payout_ngn) AS total_payout,
            COUNT(*) AS cards_count,
            SUM(ct.trade_status IN ('SUCCESS','COMPLETED','APPROVED'))   AS ok_count,
            SUM(ct.trade_status IN ('PENDING','PROCESSING'))             AS pending_count,
            SUM(ct.trade_status IN ('DECLINED','FAILED','REJECTED'))     AS bad_count,
            MAX(ct.trade_created) AS last_time
        FROM card_trade ct
        LEFT JOIN users u ON u.user_id = ct.user_id
        WHERE ct.batch_ref = '{$batch_ref_safe}'
        GROUP BY ct.batch_ref
        LIMIT 1
    ";
    if ($res = mysqli_query($conn, $sum_sql)) {
        $out['batch'] = mysqli_fetch_assoc($res) ?: null;
        mysqli_free_result($res);
    }

    // Cards in batch
    $cards_sql = "
        SELECT 
            ct.trade_id, ct.trade_ref, ct.trade_status, ct.trade_created,
            ct.card_value, ct.card_curr, ct.buy_price_snapshot, ct.est_payout_ngn,
            ct.note,
            cb.card_brand, gc.demon
        FROM card_trade ct
        LEFT JOIN card_brands cb ON cb.cbrand_id = ct.cbrand_id
        LEFT JOIN gift_cards  gc ON gc.gc_id = ct.gc_id
        WHERE ct.batch_ref = '{$batch_ref_safe}'
        ORDER BY ct.trade_created ASC, ct.trade_id ASC
    ";
    if ($cres = mysqli_query($conn, $cards_sql)) {
        while ($row = mysqli_fetch_assoc($cres)) {
            $out['cards'][] = $row;
        }
        mysqli_free_result($cres);
    }

    return $out;
}

/**
 * Images for multiple trade_ids in one call.
 * @return array trade_id => [imageRows...]
 */
function dash_get_images_for_trades(mysqli $conn, array $trade_ids): array {
    $imgs = [];
    if (empty($trade_ids)) return $imgs;
    $ids = array_map('intval', $trade_ids);
    $idlist = implode(',', $ids);

    $sql = "SELECT trade_id, image_id, path, original_name, mime, size, uploaded_at
            FROM card_trade_images
            WHERE trade_id IN ({$idlist})
            ORDER BY trade_id ASC, image_id ASC";
    if ($res = mysqli_query($conn, $sql)) {
        while ($r = mysqli_fetch_assoc($res)) {
            $tid = (int)$r['trade_id'];
            if (!isset($imgs[$tid])) $imgs[$tid] = [];
            $imgs[$tid][] = $r;
        }
        mysqli_free_result($res);
    }
    return $imgs;
}

Выполнить команду


Для локальной разработки. Не используйте в интернете!