feat(migrations): add clinic_id context to weekly_schedules, date_overrides, and holidays
- Introduced clinic_id to weekly_schedules, date_overrides, and holidays to differentiate between personal and clinic schedules. - Updated unique constraints and indexes to accommodate the new clinic context. feat(command): create AssignScheduleClinicCommand to move schedules - Added a command to move a doctor's personal weekly schedule into a clinic context. - Implemented checks to ensure sessions align with the target clinic. feat(context): implement EntityContext and EntityContextResolver - Created EntityContext to represent the effective working environment of a request (doctor or clinic). - Developed EntityContextResolver to determine the execution context based on user roles and active contexts. test: add ServiceModeContextTest for appointment scheduling - Implemented tests to ensure service booking respects clinic and personal contexts. - Verified that financial data is omitted in clinic contexts in InvitedDoctorDashboardScopeTest.
This commit is contained in:
@@ -15,17 +15,17 @@ use App\ClinicService\Repository\ServiceSectionRepository;
|
||||
use App\ClinicService\Repository\TariffRepository;
|
||||
use App\ClinicService\Service\ServiceItemAuditService;
|
||||
use App\ClinicService\Service\TariffService;
|
||||
use App\Clinic\Repository\ClinicRepository;
|
||||
use App\Doctor\Repository\DoctorRepository;
|
||||
use App\Inventory\Repository\InventoryItemRepository;
|
||||
use App\Inventory\Repository\InventoryPackageRepository;
|
||||
use App\Shared\Constant\ErrorCodes;
|
||||
use App\Shared\Context\EntityContextResolver;
|
||||
use App\Shared\Controller\BaseController;
|
||||
use App\Shared\Exception\AppException;
|
||||
use App\Staff\Repository\ClinicStaffRepository;
|
||||
use App\Subscription\Service\SubscriptionService;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\CurrentUser;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
@@ -40,8 +40,6 @@ class ClinicServiceController extends BaseController
|
||||
private readonly ServiceItemRepository $itemRepo,
|
||||
private readonly ClinicStaffRepository $staffRepo,
|
||||
private readonly SubscriptionService $subscriptionService,
|
||||
private readonly DoctorRepository $doctorRepo,
|
||||
private readonly ClinicRepository $clinicRepo,
|
||||
private readonly TariffRepository $tariffRepo,
|
||||
private readonly TariffService $tariffService,
|
||||
private readonly InventoryPackageRepository $packageRepo,
|
||||
@@ -49,6 +47,8 @@ class ClinicServiceController extends BaseController
|
||||
private readonly ServiceItemAuditService $auditService,
|
||||
private readonly ServiceItemAuditLogRepository $auditLogRepo,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly EntityContextResolver $contextResolver,
|
||||
private readonly RequestStack $requestStack,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -489,19 +489,38 @@ class ClinicServiceController extends BaseController
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* صاحب سرویسهای این درخواست. clinic_uuid درخواست (query یا body) مقدم است، بعد
|
||||
* محیط فعال کاربر، و در آخر نقش — منطق کامل در EntityContextResolver.
|
||||
*
|
||||
* @return array{0: string, 1: ?int}
|
||||
*/
|
||||
private function resolveEntity(User $user): array
|
||||
{
|
||||
if ($user->hasRole('ROLE_DOCTOR')) {
|
||||
$doctor = $this->doctorRepo->findByUser($user);
|
||||
return $doctor !== null ? ['doctor', $doctor->getId()] : ['doctor', null];
|
||||
return $this->contextResolver->resolve($user, $this->requestedClinicUuid())->toEntityPair();
|
||||
}
|
||||
|
||||
private function requestedClinicUuid(): ?string
|
||||
{
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
if ($request === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($user->hasRole('ROLE_CLINIC')) {
|
||||
$clinic = $this->clinicRepo->findByUser($user);
|
||||
return $clinic !== null ? ['clinic', $clinic->getId()] : ['clinic', null];
|
||||
$fromQuery = $request->query->get('clinic_uuid');
|
||||
if (is_string($fromQuery) && $fromQuery !== '') {
|
||||
return $fromQuery;
|
||||
}
|
||||
|
||||
return ['unknown', null];
|
||||
if (!in_array($request->getMethod(), ['POST', 'PATCH', 'PUT'], true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$body = json_decode($request->getContent(), true);
|
||||
|
||||
return is_array($body) && is_string($body['clinic_uuid'] ?? null) && $body['clinic_uuid'] !== ''
|
||||
? $body['clinic_uuid']
|
||||
: null;
|
||||
}
|
||||
|
||||
private function assertServicesGate(string $entityType, ?int $entityId): void
|
||||
|
||||
Reference in New Issue
Block a user