diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index d6b708f..f64095d 100755 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -34,8 +34,10 @@ public function users(Request $request) /** * List all subscription purchases (transactions) across users, with * filters for email, mobile (phone), package name and payment source - * (gateway). Returns paginated results with the related user, product - * and package eager-loaded for display in the admin panel. + * (gateway). Optionally narrowed to a date/time window (dates as Y-m-d, + * times as H:i or H:i:s, both in the app timezone) used by the admin + * accounting section. Returns paginated results with the related user, + * product and package eager-loaded for display in the admin panel. */ public function purchases(Request $request) { @@ -48,6 +50,11 @@ public function purchases(Request $request) // digipay, cafe, myket) or its numeric code 'gateway' => 'string|nullable', 'status' => 'integer|nullable', + 'product_id' => 'integer|nullable', + 'date_from' => 'date_format:Y-m-d|nullable', + 'date_to' => 'date_format:Y-m-d|nullable', + 'time_from' => ['nullable', 'regex:/^\d{2}:\d{2}(:\d{2})?$/'], + 'time_to' => ['nullable', 'regex:/^\d{2}:\d{2}(:\d{2})?$/'], ]); // Resolve the payment source to its stored integer code @@ -57,12 +64,26 @@ public function purchases(Request $request) ?? (is_numeric($data['gateway']) ? (int) $data['gateway'] : null); } + // Date/time window on created_at. A date without a time covers the + // whole day; a time narrows the bound to the exact datetime. Times + // only apply alongside their date (mirrors the admin panel filters). + $normalizeTime = fn ($time) => $time && strlen($time) === 5 ? $time . ':00' : $time; + $from = !empty($data['date_from']) + ? $data['date_from'] . ' ' . ($normalizeTime($data['time_from'] ?? null) ?? '00:00:00') + : null; + $to = !empty($data['date_to']) + ? $data['date_to'] . ' ' . ($normalizeTime($data['time_to'] ?? null) ?? '23:59:59') + : null; + $purchases = Transaction::with(['user', 'product.packageName']) ->when(!empty($data['email']), fn ($q) => $q->whereHas('user', fn ($u) => $u->where('email', 'like', '%' . $data['email'] . '%'))) ->when(!empty($data['mobile']), fn ($q) => $q->whereHas('user', fn ($u) => $u->where('mobile', 'like', '%' . $data['mobile'] . '%'))) ->when(!empty($data['package_name']), fn ($q) => $q->whereHas('product.packageName', fn ($p) => $p->where('name', $data['package_name']))) + ->when(!empty($data['product_id']), fn ($q) => $q->where('product_id', $data['product_id'])) ->when(!is_null($gateway), fn ($q) => $q->where('gateway', $gateway)) ->when(isset($data['status']), fn ($q) => $q->where('status', $data['status'])) + ->when($from, fn ($q) => $q->where('created_at', '>=', $from)) + ->when($to, fn ($q) => $q->where('created_at', '<=', $to)) ->latest() ->paginate($data['per_page'] ?? 30) ->withQueryString();