withoutMiddleware(EnsurePlatformSession::class); $this->owner = User::create([ 'public_id' => 'pq-access-owner', 'name' => 'Owner', 'email' => 'pq-access-owner@example.com', ]); $this->organization = Organization::create([ 'owner_ref' => $this->owner->public_id, 'name' => 'PQ Clinic', 'slug' => 'pq-clinic', 'settings' => [ 'onboarded' => true, 'facility_type' => 'clinic', 'plan' => 'pro', 'plan_expires_at' => now()->addMonth()->toIso8601String(), 'queue_integration_enabled' => true, ], ]); Member::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $this->owner->public_id, 'role' => 'hospital_admin', ]); $this->branch = Branch::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'name' => 'Main', 'is_active' => true, ]); } /** * @return array{0: User, 1: Member} */ protected function makeStaff(string $role, string $suffix): array { $user = User::create([ 'public_id' => 'pq-'.$suffix, 'name' => ucfirst($role).' '.$suffix, 'email' => $suffix.'@pq.example.com', ]); $member = Member::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'user_ref' => $user->public_id, 'role' => $role, 'branch_id' => $this->branch->id, ]); return [$user, $member]; } public function test_nurse_loses_queue_manage_and_cannot_open_patient_queue(): void { [$nurseUser, $nurseMember] = $this->makeStaff('nurse', 'nurse1'); $permissions = app(CarePermissions::class); $this->assertFalse($permissions->can($nurseMember, 'queue.manage')); $this->assertFalse($permissions->canAccessPatientQueue($nurseMember)); $this->assertTrue($permissions->handlesFloorCare($nurseMember)); $this->actingAs($nurseUser) ->get(route('care.queue.index')) ->assertForbidden(); $this->actingAs($nurseUser) ->get(route('care.dashboard')) ->assertOk() ->assertDontSee('href="'.e(route('care.queue.index')).'"', false); } public function test_receptionist_and_other_non_doctors_cannot_open_patient_queue(): void { [$receptionistUser, $receptionistMember] = $this->makeStaff('receptionist', 'rec1'); [$pharmacistUser, $pharmacistMember] = $this->makeStaff('pharmacist', 'rx1'); $permissions = app(CarePermissions::class); $this->assertFalse($permissions->canAccessPatientQueue($receptionistMember)); $this->assertFalse($permissions->canAccessPatientQueue($pharmacistMember)); $this->assertTrue($permissions->can($receptionistMember, 'queue.manage')); $this->actingAs($receptionistUser) ->get(route('care.queue.index')) ->assertForbidden(); $this->actingAs($receptionistUser) ->get(route('care.dashboard')) ->assertOk() ->assertDontSee('href="'.e(route('care.queue.index')).'"', false); $this->actingAs($pharmacistUser) ->get(route('care.queue.index')) ->assertForbidden(); } public function test_doctor_can_open_redesigned_queue_board(): void { [$doctorUser, $doctorMember] = $this->makeStaff('doctor', 'doc1'); $permissions = app(CarePermissions::class); $this->assertTrue($permissions->canAccessPatientQueue($doctorMember)); $this->actingAs($doctorUser) ->get(route('care.queue.index')) ->assertOk() ->assertSee('Patient flow') ->assertSee('Waiting') ->assertSee('Called') ->assertSee('Done'); $this->actingAs($doctorUser) ->get(route('care.dashboard')) ->assertOk() ->assertSee('Queue', false); } public function test_hospital_admin_does_not_get_patient_queue_board(): void { $adminMember = Member::query() ->where('user_ref', $this->owner->public_id) ->firstOrFail(); $permissions = app(CarePermissions::class); $this->assertFalse($permissions->canAccessPatientQueue($adminMember)); $this->assertFalse($permissions->handlesFloorCare($adminMember)); $this->actingAs($this->owner) ->get(route('care.queue.index')) ->assertForbidden(); } public function test_nurse_specialty_show_renders_list_not_auto_open_visit(): void { [$nurseUser] = $this->makeStaff('nurse', 'nurse-spec'); $modules = app(SpecialtyModuleService::class); $modules->ensureDefaultModulesProvisioned($this->organization, $this->owner->public_id); $modules->activate($this->organization->fresh(), $this->owner->public_id, 'blood_bank'); $department = Department::query() ->where('branch_id', $this->branch->id) ->where('type', 'blood_bank') ->firstOrFail(); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-BB-LIST', 'first_name' => 'Kwame', 'last_name' => 'Donor', 'gender' => 'male', 'date_of_birth' => '1988-01-01', ]); $visit = Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => Visit::STATUS_OPEN, 'checked_in_at' => now(), ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $department->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_WAITING, 'scheduled_at' => now(), 'waiting_at' => now(), 'checked_in_at' => now(), ]); $workspaceUrl = route('care.specialty.workspace', [ 'module' => 'blood_bank', 'visit' => $visit, ], absolute: false); $listHtml = $this->actingAs($nurseUser) ->get(route('care.specialty.show', 'blood_bank')) ->assertOk() ->assertSee('Blood Bank') ->assertSee('Patient flow') ->assertSee('Waiting') ->assertSee('Kwame Donor') ->assertSee('Open') ->assertDontSee('No open visit selected') ->getContent(); $this->assertStringContainsString($workspaceUrl, $listHtml); $this->assertStringNotContainsString('>Start', $listHtml); $this->actingAs($nurseUser) ->get(route('care.specialty.workspace', ['module' => 'blood_bank', 'visit' => $visit])) ->assertOk(); $this->actingAs($nurseUser) ->get(route('care.specialty.workspace', 'blood_bank')) ->assertRedirect(route('care.specialty.show', 'blood_bank')); } public function test_nurse_can_open_emergency_visit_from_specialty_list(): void { [$nurseUser] = $this->makeStaff('nurse', 'nurse-er-open'); $modules = app(SpecialtyModuleService::class); $modules->ensureDefaultModulesProvisioned($this->organization, $this->owner->public_id); $modules->activate($this->organization->fresh(), $this->owner->public_id, 'emergency'); $department = Department::query() ->where('branch_id', $this->branch->id) ->where('type', 'emergency') ->firstOrFail(); $patient = Patient::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_number' => 'P-ER-OPEN', 'first_name' => 'Akosua', 'last_name' => 'Owusu', 'gender' => 'female', 'date_of_birth' => '1990-03-15', ]); $visit = Visit::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'status' => Visit::STATUS_OPEN, 'checked_in_at' => now(), 'specialty_stage' => 'arrival', ]); Appointment::create([ 'owner_ref' => $this->owner->public_id, 'organization_id' => $this->organization->id, 'branch_id' => $this->branch->id, 'patient_id' => $patient->id, 'department_id' => $department->id, 'visit_id' => $visit->id, 'type' => Appointment::TYPE_WALK_IN, 'status' => Appointment::STATUS_WAITING, 'scheduled_at' => now(), 'waiting_at' => now(), 'checked_in_at' => now(), 'queue_ticket_number' => 'ER002', 'queue_ticket_status' => 'waiting', ]); $workspaceUrl = route('care.specialty.workspace', [ 'module' => 'emergency', 'visit' => $visit, ], absolute: false); $html = $this->actingAs($nurseUser) ->get(route('care.specialty.show', 'emergency')) ->assertOk() ->assertSee('Akosua Owusu') ->assertSee('ER002') ->assertSee('Open') ->assertDontSee('>Start', false) ->getContent(); $this->assertStringContainsString($workspaceUrl, $html); $this->actingAs($nurseUser) ->get(route('care.specialty.workspace', ['module' => 'emergency', 'visit' => $visit])) ->assertOk() ->assertSee('Akosua Owusu') ->assertDontSee('No open visit selected'); } public function test_nurse_specialty_show_redirects_to_workspace_not_queue(): void { [$nurseUser] = $this->makeStaff('nurse', 'nurse-spec-er'); app(SpecialtyModuleService::class) ->ensureDefaultModulesProvisioned($this->organization, $this->owner->public_id); app(SpecialtyModuleService::class) ->activate($this->organization->fresh(), $this->owner->public_id, 'emergency'); $this->actingAs($nurseUser) ->get(route('care.specialty.show', 'emergency')) ->assertOk() ->assertSee('Patient flow') ->assertDontSee('href="'.e(route('care.queue.index')).'"', false); } }