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); }