137 lines
5.9 KiB
PHP
137 lines
5.9 KiB
PHP
<?php
|
|
// ============================================================
|
|
// ride/siroWallet/summary.php
|
|
// ملخّص محفظة سيرو — شهري وإجمالي مع تفصيل الإيداع والصرف
|
|
// ============================================================
|
|
//
|
|
// لماذا ملف جديد بدل تعديل get.php:
|
|
// • get.php يُرجع SUM(amount) واحداً للشهر الجاري فقط، بعمود بلا اسم
|
|
// (المفتاح يصل للعميل كـ "SUM(amount)")، ولا يفرّق بين الإيداع والصرف.
|
|
// • get.php يستدعي printSuccess()/printFailure() وهما غير معرّفتين في
|
|
// payment_server/v2 إطلاقاً (لا في functions.php ولا في connect.php) —
|
|
// معرّفتان محلياً داخل ملفَّي syriatel فقط. أي أن get.php يسقط بخطأ
|
|
// "undefined function" فور اجتياز المصادقة.
|
|
// • فحص حيّ في 2026-08-03: get.php يُرجع 404 على v1 و v2 معاً — أي أنه
|
|
// غير منشور أصلاً، بينما driverWallet/get.php يُرجع 401 (موجود).
|
|
//
|
|
// لذلك هذا الملف مكتفٍ بذاته: لا يعتمد إلا على connect.php و json_encode.
|
|
//
|
|
// الرد:
|
|
// month_to_date / previous_month / all_time، ولكلٍّ:
|
|
// credits → مجموع الحركات الموجبة (إيداع)
|
|
// debits → مجموع الحركات السالبة (صرف/سحب) كقيمة موجبة
|
|
// net → الصافي
|
|
// tx_count → عدد الحركات
|
|
// by_payment_method → تفصيل الشهر الجاري حسب وسيلة الدفع
|
|
// ============================================================
|
|
|
|
require_once __DIR__ . '/../../connect.php';
|
|
|
|
// connect.php ينفّذ authenticateJWT() ويُسقط الطلب عند الفشل، فالوصول إلى
|
|
// هنا يعني توكناً صالحاً. نقصر الملخّص المالي على الأدوار الإدارية.
|
|
$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;
|
|
}
|
|
|
|
/**
|
|
* مجاميع نافذة زمنية واحدة.
|
|
* الحركات السالبة تُعاد كقيمة موجبة في debits ليقرأها العميل مباشرة.
|
|
*/
|
|
function siroWalletWindow(PDO $con, ?string $from, ?string $to): array
|
|
{
|
|
$where = '';
|
|
$params = [];
|
|
if ($from !== null && $to !== null) {
|
|
$where = 'WHERE createdAt >= :from AND createdAt < :to';
|
|
$params = [':from' => $from, ':to' => $to];
|
|
}
|
|
|
|
$stmt = $con->prepare("
|
|
SELECT
|
|
COALESCE(SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END), 0) AS credits,
|
|
COALESCE(SUM(CASE WHEN amount < 0 THEN -amount ELSE 0 END), 0) AS debits,
|
|
COALESCE(SUM(amount), 0) AS net,
|
|
COUNT(*) AS tx_count
|
|
FROM `siroWallet`
|
|
$where
|
|
");
|
|
$stmt->execute($params);
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC) ?: [];
|
|
|
|
return [
|
|
'credits' => (float)($row['credits'] ?? 0),
|
|
'debits' => (float)($row['debits'] ?? 0),
|
|
'net' => (float)($row['net'] ?? 0),
|
|
'tx_count' => (int) ($row['tx_count'] ?? 0),
|
|
];
|
|
}
|
|
|
|
try {
|
|
// حدود الشهر تُحسب في PHP لا في SQL، حتى تتبع المنطقة الزمنية للتطبيق
|
|
// ويسهل اختبارها، ولتفادي BETWEEN على TIMESTAMP الذي يُسقط آخر يوم.
|
|
$startThisMonth = date('Y-m-01 00:00:00');
|
|
$startNextMonth = date('Y-m-01 00:00:00', strtotime('first day of next month'));
|
|
$startPrevMonth = date('Y-m-01 00:00:00', strtotime('first day of last month'));
|
|
|
|
$monthToDate = siroWalletWindow($con, $startThisMonth, $startNextMonth);
|
|
$previousMonth = siroWalletWindow($con, $startPrevMonth, $startThisMonth);
|
|
$allTime = siroWalletWindow($con, null, null);
|
|
|
|
// تفصيل الشهر الجاري حسب وسيلة الدفع
|
|
$stmt = $con->prepare("
|
|
SELECT
|
|
paymentMethod,
|
|
COALESCE(SUM(amount), 0) AS net,
|
|
COUNT(*) AS tx_count
|
|
FROM `siroWallet`
|
|
WHERE createdAt >= :from AND createdAt < :to
|
|
GROUP BY paymentMethod
|
|
ORDER BY net DESC
|
|
");
|
|
$stmt->execute([':from' => $startThisMonth, ':to' => $startNextMonth]);
|
|
|
|
$byMethod = [];
|
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
|
$byMethod[] = [
|
|
'payment_method' => $r['paymentMethod'] !== '' ? $r['paymentMethod'] : 'unknown',
|
|
'net' => (float)$r['net'],
|
|
'tx_count' => (int)$r['tx_count'],
|
|
];
|
|
}
|
|
|
|
// نسبة التغيّر عن الشهر السابق — الواجهة تعرضها كمؤشّر اتجاه
|
|
$prevNet = $previousMonth['net'];
|
|
$growth = ($prevNet != 0.0)
|
|
? round((($monthToDate['net'] - $prevNet) / abs($prevNet)) * 100, 2)
|
|
: null;
|
|
|
|
echo json_encode([
|
|
'status' => 'success',
|
|
'data' => [
|
|
'month_to_date' => $monthToDate,
|
|
'previous_month' => $previousMonth,
|
|
'all_time' => $allTime,
|
|
'growth_percent' => $growth, // null عندما لا يوجد أساس للمقارنة
|
|
'by_payment_method' => $byMethod,
|
|
'period' => [
|
|
'month_start' => $startThisMonth,
|
|
'generated_at' => date('Y-m-d H:i:s'),
|
|
],
|
|
],
|
|
], JSON_UNESCAPED_UNICODE);
|
|
|
|
} catch (Throwable $e) {
|
|
error_log('[siroWallet/summary] ' . $e->getMessage());
|
|
http_response_code(500);
|
|
echo json_encode([
|
|
'status' => 'failure',
|
|
'message' => 'An internal error occurred.',
|
|
], JSON_UNESCAPED_UNICODE);
|
|
}
|