feat: implement admin API for user and representation management
- Updated UsersPage to fetch users from the new admin endpoint. - Enhanced user data structure to include 'name' and modified rendering logic. - Added RepresentationDetailPage for detailed representation management. - Created AdminApiController to handle user and representation CRUD operations. - Implemented pagination and search functionality for users and representations. - Updated user and representation data models to reflect new API structure.
This commit is contained in:
@@ -0,0 +1,522 @@
|
||||
<?php
|
||||
|
||||
namespace App\Admin\Controller;
|
||||
|
||||
use App\Appointment\Entity\Appointment;
|
||||
use App\Auth\Entity\User;
|
||||
use App\Clinic\Entity\Clinic;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Payment\Entity\Payment;
|
||||
use App\Rating\Entity\Comment;
|
||||
use App\Rating\Entity\Rate;
|
||||
use App\Representation\Entity\Representation;
|
||||
use App\Secretary\Entity\DoctorSecretary;
|
||||
use App\Settlement\Entity\Settlement;
|
||||
use App\Sms\Entity\SmsLog;
|
||||
use App\Sms\Entity\SmsTemplate;
|
||||
use App\Shared\Controller\BaseController;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
class AdminApiController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
) {}
|
||||
|
||||
// ── Users ─────────────────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/users', methods: ['GET'])]
|
||||
public function users(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$search = trim((string) $request->query->get('search', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select('u.uuid, u.id, u.mobileNumber as mobile, u.realName as name, u.email, u.roles, u.status, u.createdAt')
|
||||
->from(User::class, 'u')
|
||||
->orderBy('u.createdAt', 'DESC');
|
||||
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('u.mobileNumber LIKE :s OR u.realName LIKE :s OR u.email LIKE :s')
|
||||
->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(u.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $u) => [
|
||||
'uuid' => $u['uuid'],
|
||||
'id' => $u['id'],
|
||||
'mobile_number' => $u['mobile'],
|
||||
'name' => $u['name'],
|
||||
'email' => $u['email'],
|
||||
'roles' => $u['roles'],
|
||||
'is_active' => $u['status'] === 1,
|
||||
'created_at' => date('c', (int) $u['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── Appointments ──────────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/appointments', methods: ['GET'])]
|
||||
public function appointments(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$search = trim((string) $request->query->get('search', ''));
|
||||
$status = trim((string) $request->query->get('status', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select(
|
||||
'a.uuid, a.slotStart, a.slotEnd, a.status, a.createdAt',
|
||||
'd.uuid as doctor_uuid, d.name as doctor_name',
|
||||
'u.mobileNumber as patient_mobile, u.realName as patient_name',
|
||||
)
|
||||
->from(Appointment::class, 'a')
|
||||
->join('a.doctor', 'd')
|
||||
->join('a.user', 'u')
|
||||
->orderBy('a.createdAt', 'DESC');
|
||||
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('u.mobileNumber LIKE :s OR d.name LIKE :s')
|
||||
->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
if ($status !== '') {
|
||||
$qb->andWhere('a.status = :status')->setParameter('status', $status);
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(a.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $a) => [
|
||||
'uuid' => $a['uuid'],
|
||||
'patient_name' => $a['patient_name'] ?? '',
|
||||
'patient_mobile' => $a['patient_mobile'],
|
||||
'doctor_name' => $a['doctor_name'],
|
||||
'appointment_date' => date('Y-m-d', (int) $a['slotStart']),
|
||||
'appointment_time' => date('H:i', (int) $a['slotStart']),
|
||||
'status' => $a['status'],
|
||||
'amount' => 0,
|
||||
'created_at' => date('c', (int) $a['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── Payments ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/payments', methods: ['GET'])]
|
||||
public function payments(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$search = trim((string) $request->query->get('search', ''));
|
||||
$status = trim((string) $request->query->get('status', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select(
|
||||
'p.uuid, p.amountRials, p.status, p.gateway, p.referenceId, p.createdAt, p.updatedAt',
|
||||
'u.mobileNumber as patient_mobile',
|
||||
)
|
||||
->from(Payment::class, 'p')
|
||||
->join('p.user', 'u')
|
||||
->orderBy('p.createdAt', 'DESC');
|
||||
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('u.mobileNumber LIKE :s OR p.referenceId LIKE :s OR p.orderId LIKE :s')
|
||||
->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
if ($status !== '') {
|
||||
$qb->andWhere('p.status = :status')->setParameter('status', $status);
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(p.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $p) => [
|
||||
'uuid' => $p['uuid'],
|
||||
'amount' => (int) $p['amountRials'],
|
||||
'status' => $p['status'],
|
||||
'gateway' => $p['gateway'],
|
||||
'ref_id' => $p['referenceId'],
|
||||
'patient_mobile' => $p['patient_mobile'],
|
||||
'paid_at' => $p['status'] === 'success' ? date('c', (int) $p['updatedAt']) : null,
|
||||
'created_at' => date('c', (int) $p['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── Representations ───────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/representations', methods: ['GET'])]
|
||||
public function representations(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$search = trim((string) $request->query->get('search', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select('r.uuid, r.fullName, r.mobileNumber, r.city, r.commissionPercent, r.active, r.createdAt')
|
||||
->from(Representation::class, 'r')
|
||||
->orderBy('r.createdAt', 'DESC');
|
||||
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('r.fullName LIKE :s OR r.city LIKE :s')
|
||||
->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(r.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $r) => [
|
||||
'uuid' => $r['uuid'],
|
||||
'domain' => $r['fullName'],
|
||||
'full_name' => $r['fullName'],
|
||||
'mobile_number' => $r['mobileNumber'],
|
||||
'city' => $r['city'] ?? '',
|
||||
'commission_percent' => (float) $r['commissionPercent'],
|
||||
'wallet_balance' => 0,
|
||||
'is_active' => (bool) $r['active'],
|
||||
'created_at' => date('c', (int) $r['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── Secretaries ───────────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/secretaries', methods: ['GET'])]
|
||||
public function secretaries(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$search = trim((string) $request->query->get('search', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select(
|
||||
'ds.uuid, ds.permissions, ds.active, ds.createdAt',
|
||||
'u.mobileNumber as mobile, u.realName as user_name',
|
||||
'd.name as doctor_name, d.uuid as doctor_uuid',
|
||||
)
|
||||
->from(DoctorSecretary::class, 'ds')
|
||||
->join('ds.doctor', 'd')
|
||||
->join('ds.secretary', 'u')
|
||||
->orderBy('ds.createdAt', 'DESC');
|
||||
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('u.mobileNumber LIKE :s OR u.realName LIKE :s OR d.name LIKE :s')
|
||||
->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(ds.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $ds) => [
|
||||
'uuid' => $ds['uuid'],
|
||||
'user_name' => $ds['user_name'] ?? $ds['mobile'],
|
||||
'mobile_number' => $ds['mobile'],
|
||||
'doctor_name' => $ds['doctor_name'],
|
||||
'doctor_uuid' => $ds['doctor_uuid'],
|
||||
'is_active' => (bool) $ds['active'],
|
||||
'permissions' => $ds['permissions'] ?? DoctorSecretary::DEFAULT_PERMISSIONS,
|
||||
'created_at' => date('c', (int) $ds['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── Ratings ───────────────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/rates', methods: ['GET'])]
|
||||
public function rates(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$search = trim((string) $request->query->get('search', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select(
|
||||
'r.uuid, r.score, r.createdAt',
|
||||
'u.realName as patient_name, u.mobileNumber as patient_mobile',
|
||||
'd.name as doctor_name',
|
||||
)
|
||||
->from(Rate::class, 'r')
|
||||
->join('r.doctor', 'd')
|
||||
->join('r.user', 'u')
|
||||
->orderBy('r.createdAt', 'DESC');
|
||||
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('d.name LIKE :s OR u.realName LIKE :s')
|
||||
->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(r.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $r) => [
|
||||
'uuid' => $r['uuid'],
|
||||
'patient_name' => $r['patient_name'] ?? $r['patient_mobile'],
|
||||
'doctor_name' => $r['doctor_name'],
|
||||
'overall' => (int) $r['score'],
|
||||
'score' => (int) $r['score'],
|
||||
'created_at' => date('c', (int) $r['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── Comments ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/comments', methods: ['GET'])]
|
||||
public function comments(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$search = trim((string) $request->query->get('search', ''));
|
||||
$status = trim((string) $request->query->get('status', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select(
|
||||
'c.uuid, c.body, c.status, c.createdAt',
|
||||
'u.realName as patient_name',
|
||||
'd.name as doctor_name',
|
||||
)
|
||||
->from(Comment::class, 'c')
|
||||
->join('c.doctor', 'd')
|
||||
->join('c.user', 'u')
|
||||
->orderBy('c.createdAt', 'DESC');
|
||||
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('d.name LIKE :s OR c.body LIKE :s OR u.realName LIKE :s')
|
||||
->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
if ($status !== '') {
|
||||
$qb->andWhere('c.status = :status')->setParameter('status', $status);
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(c.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $c) => [
|
||||
'uuid' => $c['uuid'],
|
||||
'patient_name' => $c['patient_name'] ?? '',
|
||||
'doctor_name' => $c['doctor_name'],
|
||||
'title' => mb_substr($c['body'], 0, 50),
|
||||
'body' => $c['body'],
|
||||
'is_approved' => $c['status'] === 'approved',
|
||||
'status' => $c['status'],
|
||||
'created_at' => date('c', (int) $c['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── SMS Logs ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/sms/logs', methods: ['GET'])]
|
||||
public function smsLogs(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select('s.uuid, s.mobile, s.message, s.provider, s.success, s.createdAt')
|
||||
->from(SmsLog::class, 's')
|
||||
->orderBy('s.createdAt', 'DESC');
|
||||
|
||||
$total = (clone $qb)->select('COUNT(s.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $l) => [
|
||||
'uuid' => $l['uuid'],
|
||||
'recipient' => $l['mobile'],
|
||||
'message' => $l['message'],
|
||||
'status' => $l['success'] ? 'sent' : 'failed',
|
||||
'provider' => $l['provider'],
|
||||
'sent_at' => date('c', (int) $l['createdAt']),
|
||||
'created_at' => date('c', (int) $l['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── Settlements ───────────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/settlements', methods: ['GET'])]
|
||||
public function settlements(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$status = trim((string) $request->query->get('status', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select(
|
||||
's.uuid, s.amountRials, s.status, s.bankAccount, s.adminNote, s.reviewedAt, s.createdAt',
|
||||
'u.realName as user_name, u.mobileNumber as user_mobile',
|
||||
)
|
||||
->from(Settlement::class, 's')
|
||||
->join('s.user', 'u')
|
||||
->orderBy('s.createdAt', 'DESC');
|
||||
|
||||
if ($status !== '') {
|
||||
$qb->andWhere('s.status = :status')->setParameter('status', $status);
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(s.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $s) => [
|
||||
'uuid' => $s['uuid'],
|
||||
'representation_name' => $s['user_name'] ?? $s['user_mobile'],
|
||||
'amount' => (int) $s['amountRials'],
|
||||
'status' => $s['status'],
|
||||
'bank_card' => $s['bankAccount']['card'] ?? null,
|
||||
'bank_name' => $s['bankAccount']['bank_name'] ?? null,
|
||||
'reject_reason' => $s['adminNote'],
|
||||
'requested_at' => date('c', (int) $s['createdAt']),
|
||||
'processed_at' => $s['reviewedAt'] ? date('c', (int) $s['reviewedAt']) : null,
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── SMS Templates (paginated list with optional status filter) ────────────
|
||||
|
||||
#[Route('/api/v1/admin/sms/sample-templates', methods: ['GET'])]
|
||||
public function smsSampleTemplates(Request $request): JsonResponse
|
||||
{
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$status = trim((string) $request->query->get('status', 'approved'));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select('t.uuid, t.name, t.body, t.providerCode, t.status, t.adminNote, t.createdAt')
|
||||
->from(SmsTemplate::class, 't')
|
||||
->orderBy('t.createdAt', 'DESC');
|
||||
|
||||
if ($status !== '') {
|
||||
$qb->where('t.status = :status')->setParameter('status', $status);
|
||||
}
|
||||
|
||||
$total = (clone $qb)->select('COUNT(t.id)')->getQuery()->getSingleScalarResult();
|
||||
|
||||
$rows = $qb->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$items = array_map(fn(array $t) => [
|
||||
'uuid' => $t['uuid'],
|
||||
'name' => $t['name'],
|
||||
'body' => $t['body'],
|
||||
'provider_code' => $t['providerCode'],
|
||||
'status' => $t['status'],
|
||||
'admin_note' => $t['adminNote'],
|
||||
'created_at' => date('c', (int) $t['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
// ── Dashboard Stats ───────────────────────────────────────────────────────
|
||||
|
||||
#[Route('/api/v1/admin/dashboard/stats', methods: ['GET'])]
|
||||
public function dashboardStats(): JsonResponse
|
||||
{
|
||||
$em = $this->em;
|
||||
|
||||
$todayStart = mktime(0, 0, 0);
|
||||
$todayEnd = mktime(23, 59, 59);
|
||||
|
||||
$totalUsers = (int) $em->createQueryBuilder()
|
||||
->select('COUNT(u.id)')->from(User::class, 'u')
|
||||
->getQuery()->getSingleScalarResult();
|
||||
|
||||
$activeDoctors = (int) $em->createQueryBuilder()
|
||||
->select('COUNT(d.id)')->from(Doctor::class, 'd')
|
||||
->where('d.activeDoctorAppointment = true')
|
||||
->getQuery()->getSingleScalarResult();
|
||||
|
||||
$totalDoctors = (int) $em->createQueryBuilder()
|
||||
->select('COUNT(d.id)')->from(Doctor::class, 'd')
|
||||
->getQuery()->getSingleScalarResult();
|
||||
|
||||
$totalClinics = (int) $em->createQueryBuilder()
|
||||
->select('COUNT(c.id)')->from(Clinic::class, 'c')
|
||||
->getQuery()->getSingleScalarResult();
|
||||
|
||||
$todayAppointments = (int) $em->createQueryBuilder()
|
||||
->select('COUNT(a.id)')->from(Appointment::class, 'a')
|
||||
->where('a.slotStart BETWEEN :s AND :e')
|
||||
->setParameter('s', $todayStart)->setParameter('e', $todayEnd)
|
||||
->getQuery()->getSingleScalarResult();
|
||||
|
||||
$totalAppointments = (int) $em->createQueryBuilder()
|
||||
->select('COUNT(a.id)')->from(Appointment::class, 'a')
|
||||
->getQuery()->getSingleScalarResult();
|
||||
|
||||
$todayPaymentsResult = $em->createQueryBuilder()
|
||||
->select('COUNT(p.id) as cnt, COALESCE(SUM(p.amountRials), 0) as total')
|
||||
->from(Payment::class, 'p')
|
||||
->where('p.status = :s AND p.createdAt BETWEEN :ts AND :te')
|
||||
->setParameter('s', Payment::STATUS_SUCCESS)
|
||||
->setParameter('ts', $todayStart)->setParameter('te', $todayEnd)
|
||||
->getQuery()->getSingleResult();
|
||||
|
||||
$totalPaymentsResult = $em->createQueryBuilder()
|
||||
->select('COUNT(p.id) as cnt, COALESCE(SUM(p.amountRials), 0) as total')
|
||||
->from(Payment::class, 'p')
|
||||
->where('p.status = :s')
|
||||
->setParameter('s', Payment::STATUS_SUCCESS)
|
||||
->getQuery()->getSingleResult();
|
||||
|
||||
$pendingComments = (int) $em->createQueryBuilder()
|
||||
->select('COUNT(c.id)')->from(Comment::class, 'c')
|
||||
->where('c.status = :s')->setParameter('s', Comment::STATUS_PENDING)
|
||||
->getQuery()->getSingleScalarResult();
|
||||
|
||||
$pendingSettlements = (int) $em->createQueryBuilder()
|
||||
->select('COUNT(s.id)')->from(Settlement::class, 's')
|
||||
->where('s.status = :s')->setParameter('s', Settlement::STATUS_PENDING)
|
||||
->getQuery()->getSingleScalarResult();
|
||||
|
||||
return $this->success([
|
||||
'total_users' => $totalUsers,
|
||||
'active_doctors' => $activeDoctors,
|
||||
'total_doctors' => $totalDoctors,
|
||||
'total_clinics' => $totalClinics,
|
||||
'today_appointments' => $todayAppointments,
|
||||
'total_appointments' => $totalAppointments,
|
||||
'today_payments_count' => (int) $todayPaymentsResult['cnt'],
|
||||
'today_payments_amount' => (int) $todayPaymentsResult['total'],
|
||||
'total_payments_amount' => (int) $totalPaymentsResult['total'],
|
||||
'pending_comments' => $pendingComments,
|
||||
'pending_settlements' => $pendingSettlements,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user