feat(api): add dashboard endpoints for clinic, doctor, and secretary roles
- Implemented GET /api/v1/dashboard/clinic to return clinic stats and today's schedule for clinic owners. - Implemented GET /api/v1/dashboard/doctor to return doctor's stats and today's schedule for doctors. - Implemented GET /api/v1/dashboard/secretary to return stats and conditional appointments for secretaries. feat(migrations): create user_active_context and mobile_verification_otp tables - Added migration to create user_active_context table for tracking active user sessions. - Added migration to create mobile_verification_otp table for handling mobile number verification. feat(migrations): create site_config table for application settings - Added migration to create site_config table to store various site configuration settings. feat(appointments): create MyAppointmentsController for user-specific appointments - Added MyAppointmentsController to handle fetching user-specific appointments with pagination and filtering. feat(auth): implement NotificationMobileController for mobile number verification - Added NotificationMobileController to handle OTP requests and verification for mobile number changes. feat(auth): create MobileVerificationOtp entity for OTP management - Created MobileVerificationOtp entity to manage OTP records for mobile verification. feat(auth): create UserActiveContext entity for user session management - Created UserActiveContext entity to manage user active sessions. feat(config): implement SiteConfigController for managing site settings - Added SiteConfigController to handle fetching and updating site configuration settings. feat(config): create SiteConfig entity and repository for configuration management - Created SiteConfig entity and repository to manage site configuration data.
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Appointment\Controller;
|
||||
|
||||
use App\Appointment\Entity\Appointment;
|
||||
use App\Auth\Entity\User;
|
||||
use App\Clinic\Repository\ClinicRepository;
|
||||
use App\Doctor\Repository\DoctorRepository;
|
||||
use App\Secretary\Repository\DoctorSecretaryRepository;
|
||||
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\CurrentUser;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class MyAppointmentsController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly DoctorRepository $doctorRepo,
|
||||
private readonly ClinicRepository $clinicRepo,
|
||||
private readonly DoctorSecretaryRepository $secretaryRepo,
|
||||
) {}
|
||||
|
||||
#[Route('/api/v1/my/appointments', methods: ['GET'])]
|
||||
#[IsGranted('IS_AUTHENTICATED_FULLY')]
|
||||
public function myAppointments(Request $request, #[CurrentUser] User $user): 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', ''));
|
||||
$date = trim((string) $request->query->get('date', ''));
|
||||
|
||||
$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',
|
||||
'c.name as clinic_name'
|
||||
)
|
||||
->from(Appointment::class, 'a')
|
||||
->join('a.doctor', 'd')
|
||||
->join('a.user', 'u')
|
||||
->leftJoin('App\Clinic\Entity\Clinic', 'c', 'WITH', 'd MEMBER OF c.doctors')
|
||||
->orderBy('a.slotStart', 'DESC');
|
||||
|
||||
$roles = $user->getRoles();
|
||||
|
||||
if (in_array('ROLE_ADMIN', $roles, true)) {
|
||||
// Admin voit tout
|
||||
} elseif (in_array('ROLE_CLINIC', $roles, true)) {
|
||||
$clinic = $this->clinicRepo->findByUser($user);
|
||||
if ($clinic === null) {
|
||||
return $this->paginated([], 0, $page, $limit);
|
||||
}
|
||||
$qb->andWhere(':clinic MEMBER OF d.clinics')
|
||||
->setParameter('clinic', $clinic);
|
||||
} elseif (in_array('ROLE_DOCTOR', $roles, true)) {
|
||||
$doctor = $this->doctorRepo->findByUser($user);
|
||||
if ($doctor === null) {
|
||||
return $this->paginated([], 0, $page, $limit);
|
||||
}
|
||||
$qb->andWhere('a.doctor = :doctor')
|
||||
->setParameter('doctor', $doctor);
|
||||
} elseif (in_array('ROLE_SECRETARY', $roles, true)) {
|
||||
$rel = $this->secretaryRepo->findActiveBySecretary($user);
|
||||
if ($rel === null) {
|
||||
return $this->paginated([], 0, $page, $limit);
|
||||
}
|
||||
$canView = (bool) ($rel->getPermissions()['resources']['appointments']['view'] ?? false);
|
||||
if (!$canView) {
|
||||
return $this->paginated([], 0, $page, $limit);
|
||||
}
|
||||
$qb->andWhere('a.doctor = :doctor')
|
||||
->setParameter('doctor', $rel->getDoctor());
|
||||
} else {
|
||||
return $this->paginated([], 0, $page, $limit);
|
||||
}
|
||||
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('u.mobileNumber LIKE :s OR d.name LIKE :s OR u.realName LIKE :s')
|
||||
->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
if ($status !== '') {
|
||||
$qb->andWhere('a.status = :status')->setParameter('status', $status);
|
||||
}
|
||||
if ($date !== '') {
|
||||
$dayStart = strtotime($date . ' 00:00:00');
|
||||
$dayEnd = strtotime($date . ' 23:59:59');
|
||||
if ($dayStart && $dayEnd) {
|
||||
$qb->andWhere('a.slotStart >= :dayStart AND a.slotStart <= :dayEnd')
|
||||
->setParameter('dayStart', $dayStart)
|
||||
->setParameter('dayEnd', $dayEnd);
|
||||
}
|
||||
}
|
||||
|
||||
$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'],
|
||||
'clinic_name' => $a['clinic_name'] ?? null,
|
||||
'appointment_date' => date('Y-m-d', (int) $a['slotStart']),
|
||||
'appointment_time' => date('H:i', (int) $a['slotStart']),
|
||||
'slot_start' => (int) $a['slotStart'],
|
||||
'status' => $a['status'],
|
||||
'amount' => 0,
|
||||
'created_at' => date('c', (int) $a['createdAt']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, (int) $total, $page, $limit);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user