Files
tripz-llc/payment_server/v2/main/ride/driverPayment/withdrawal_requests.php
T
2026-08-09 16:56:13 +03:00

166 lines
6.6 KiB
PHP

<?php
// ============================================================
// ride/driverPayment/withdrawal_requests.php
// قائمة طلبات سحب أرصدة السائقين للوحة التحكم
// ============================================================
//
// لماذا هذا الملف:
// جدول `driver_withdrawal_requests` يُكتب فيه من
// ride/mtn/driver_payout_syria.php عند طلب السائق السحب، لكن **لا شيء في
// المنصّة كلها يقرأه** — لا نقطة في الباك إند ولا شاشة في لوحة التحكم
// (تحقّقت بمسح كامل على backend/ و payment_server/ و siro_admin/).
// أي أن طلبات السحب كانت تتراكم دون أن يراها أحد، والإشعار الوحيد رسالة
// واتساب لحظية عند الإرسال — تضيع إن فات وقتها.
//
// GET : قائمة الطلبات مع تصفية بالحالة + مجاميع لكل حالة
// POST : تحديث حالة طلب (approved / rejected / paid)
// ============================================================
require_once __DIR__ . '/../../connect.php';
$role = $decodedToken->role ?? null;
if ($role !== 'admin' && $role !== 'super_admin') {
http_response_code(403);
echo json_encode([
'status' => 'failure',
'message' => 'Forbidden. Admin access required.',
], JSON_UNESCAPED_UNICODE);
exit;
}
// الحالات المسموح بها — قائمة مغلقة حتى لا تُكتب حالة عشوائية في الجدول
const WITHDRAWAL_STATUSES = ['pending', 'approved', 'rejected', 'paid'];
// التوجيه بحقل action لا بطريقة HTTP: عميل اللوحة (CRUD.getWallet في
// siro_admin) يرسل كل الطلبات بـ POST form-encoded، فالتفريق بالطريقة كان
// سيوجّه طلبات العرض إلى فرع التحديث.
$body = $_POST;
if (empty($body)) {
$raw = json_decode(file_get_contents('php://input'), true);
if (is_array($raw)) $body = $raw;
}
$action = $body['action'] ?? $_GET['action'] ?? 'list';
try {
// ── تحديث حالة طلب ───────────────────────────────────────
if ($action === 'update_status') {
// صرف المال فعلياً قرار لا رجعة فيه — نقصره على super_admin
if ($role !== 'super_admin') {
http_response_code(403);
echo json_encode([
'status' => 'failure',
'message' => 'Forbidden. Super Admin required to change withdrawal status.',
], JSON_UNESCAPED_UNICODE);
exit;
}
$id = isset($body['id']) ? (int)$body['id'] : 0;
$status = trim((string)($body['status'] ?? ''));
if ($id <= 0 || !in_array($status, WITHDRAWAL_STATUSES, true)) {
http_response_code(400);
echo json_encode([
'status' => 'failure',
'message' => 'Invalid id or status. Allowed: ' . implode(', ', WITHDRAWAL_STATUSES),
], JSON_UNESCAPED_UNICODE);
exit;
}
// لا نسمح بتعديل طلب خرج من pending إلا إلى paid — يمنع عكس رفض
// أو إعادة اعتماد طلب مدفوع بالخطأ.
$cur = $con->prepare("SELECT status FROM driver_withdrawal_requests WHERE id = ?");
$cur->execute([$id]);
$current = $cur->fetchColumn();
if ($current === false) {
http_response_code(404);
echo json_encode(['status' => 'failure', 'message' => 'Request not found.'], JSON_UNESCAPED_UNICODE);
exit;
}
if ($current !== 'pending' && !($current === 'approved' && $status === 'paid')) {
http_response_code(409);
echo json_encode([
'status' => 'failure',
'message' => "Cannot change status from '$current' to '$status'.",
], JSON_UNESCAPED_UNICODE);
exit;
}
$upd = $con->prepare("UPDATE driver_withdrawal_requests SET status = ? WHERE id = ?");
$upd->execute([$status, $id]);
error_log("[withdrawal_requests] id=$id '$current' -> '$status' by " . ($decodedToken->user_id ?? 'unknown'));
echo json_encode([
'status' => 'success',
'data' => ['id' => $id, 'from' => $current, 'to' => $status],
], JSON_UNESCAPED_UNICODE);
exit;
}
// ── قائمة الطلبات ────────────────────────────────────────
$filter = $body['status'] ?? $_GET['status'] ?? 'pending';
$limit = (int)($body['limit'] ?? $_GET['limit'] ?? 100);
$limit = max(1, min(200, $limit));
$where = '';
$params = [];
if ($filter !== 'all') {
if (!in_array($filter, WITHDRAWAL_STATUSES, true)) {
http_response_code(400);
echo json_encode(['status' => 'failure', 'message' => 'Invalid status filter.'], JSON_UNESCAPED_UNICODE);
exit;
}
$where = 'WHERE status = :status';
$params = [':status' => $filter];
}
$stmt = $con->prepare("
SELECT id, driver_id, driver_name, amount, wallet_type, wallet_number,
status, created_at, updated_at
FROM driver_withdrawal_requests
$where
ORDER BY created_at DESC
LIMIT $limit
");
$stmt->execute($params);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as &$r) {
$r['amount'] = (float)$r['amount'];
$r['id'] = (int)$r['id'];
}
unset($r);
// مجاميع لكل حالة — تغذّي شارات العدّ في اللوحة دون طلب إضافي
$totals = [];
$agg = $con->query("
SELECT status, COUNT(*) AS cnt, COALESCE(SUM(amount), 0) AS total
FROM driver_withdrawal_requests
GROUP BY status
");
foreach ($agg->fetchAll(PDO::FETCH_ASSOC) as $a) {
$totals[$a['status']] = [
'count' => (int)$a['cnt'],
'total' => (float)$a['total'],
];
}
echo json_encode([
'status' => 'success',
'data' => [
'filter' => $filter,
'requests' => $rows,
'totals' => $totals,
],
], JSON_UNESCAPED_UNICODE);
} catch (Throwable $e) {
error_log('[withdrawal_requests] ' . $e->getMessage());
http_response_code(500);
echo json_encode([
'status' => 'failure',
'message' => 'An internal error occurred.',
], JSON_UNESCAPED_UNICODE);
}