diff --git a/app/Http/Controllers/Care/SpecialtyModuleController.php b/app/Http/Controllers/Care/SpecialtyModuleController.php index bf9ddf7..ca5a90d 100644 --- a/app/Http/Controllers/Care/SpecialtyModuleController.php +++ b/app/Http/Controllers/Care/SpecialtyModuleController.php @@ -563,6 +563,7 @@ class SpecialtyModuleController extends Controller abort_unless($modules->memberCanAccess($organization, $member, $module), 403); $canManageSpecialty = $modules->memberCanManage($organization, $member, $module); + $canViewSpecialty = $modules->memberCanView($organization, $member, $module); $canReferSpecialty = $modules->memberCanRefer($organization, $member, $module); $specialtyAccessLevel = $modules->memberAccessLevel($organization, $member, $module); @@ -881,6 +882,7 @@ class SpecialtyModuleController extends Controller 'canConsult' => $canConsult, 'canManageQueue' => $canManageQueue, 'canManageSpecialty' => $canManageSpecialty, + 'canViewSpecialty' => $canViewSpecialty, 'canReferSpecialty' => $canReferSpecialty, 'specialtyAccessLevel' => $specialtyAccessLevel, 'queueIntegration' => $branchId diff --git a/resources/views/care/specialty/dentistry/workspace-imaging.blade.php b/resources/views/care/specialty/dentistry/workspace-imaging.blade.php index b178ee7..50a695b 100644 --- a/resources/views/care/specialty/dentistry/workspace-imaging.blade.php +++ b/resources/views/care/specialty/dentistry/workspace-imaging.blade.php @@ -1,48 +1,52 @@ +@php $canManage = $canManageSpecialty ?? true; @endphp +

Dental imaging

Upload PA, bitewing, OPG, or clinical photos linked to teeth.

-
- @csrf -
-
- - -
-
- - -
-
- - -
-
-

Teeth

-
- @foreach (array_merge($dentalRows['upper'] ?? [], $dentalRows['lower'] ?? []) as $code) - - @endforeach + @if ($canManage) + + @csrf +
+
+ + +
+
+ + +
+
+ + +
+
+

Teeth

+
+ @foreach (array_merge($dentalRows['upper'] ?? [], $dentalRows['lower'] ?? []) as $code) + + @endforeach +
+
+
+
-
- -
-
- - + + + @endif -
+
true, 'mt-4' => ! $canManage])> @forelse ($dentalImages as $image) @php $url = $image->attachment?->file_path @@ -71,10 +75,12 @@

{{ $image->caption }}

@endif
-
- @csrf - -
+ @if ($canManage) +
+ @csrf + +
+ @endif
diff --git a/resources/views/care/specialty/dentistry/workspace-lab.blade.php b/resources/views/care/specialty/dentistry/workspace-lab.blade.php index 93eded7..29e6d35 100644 --- a/resources/views/care/specialty/dentistry/workspace-lab.blade.php +++ b/resources/views/care/specialty/dentistry/workspace-lab.blade.php @@ -1,3 +1,5 @@ +@php $canManage = $canManageSpecialty ?? true; @endphp +

Lab cases

Track crowns, bridges, dentures, and other lab work.

@@ -17,7 +19,7 @@ @if ($case->due_at) · due {{ $case->due_at->format('d M Y') }} @endif

- @if ($case->status !== 'cancelled' && $case->status !== 'fitted') + @if ($canManage && $case->status !== 'cancelled' && $case->status !== 'fitted')
@csrf - @foreach ($dentalLabCaseTypes ?? [] as $value => $label) - - @endforeach - - -
- - -
-
- - -
-
- - -
-
-

Teeth

-
- @foreach (array_merge($dentalRows['upper'] ?? [], $dentalRows['lower'] ?? []) as $code) - - @endforeach + @if ($canManage) + + @csrf +

New lab case

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+

Teeth

+
+ @foreach (array_merge($dentalRows['upper'] ?? [], $dentalRows['lower'] ?? []) as $code) + + @endforeach +
+
+
+ +
-
- - -
-
- - + + + @endif
diff --git a/resources/views/care/specialty/dentistry/workspace-notes.blade.php b/resources/views/care/specialty/dentistry/workspace-notes.blade.php index 788f17d..d48531a 100644 --- a/resources/views/care/specialty/dentistry/workspace-notes.blade.php +++ b/resources/views/care/specialty/dentistry/workspace-notes.blade.php @@ -1,25 +1,48 @@ +@php $canManage = $canManageSpecialty ?? true; @endphp +

Dental visit notes

Short clinical notes for this visit — not a GP SOAP form.

-
- @csrf -
- - -
-
- - -
-
- - -
-
- - -
- -
+ @if ($canManage) +
+ @csrf +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ @else +
+
+
Chief complaint
+
{{ $dentalVisitNote?->chief_complaint ?: '—' }}
+
+
+
Soft tissue
+
{{ $dentalVisitNote?->soft_tissue ?: '—' }}
+
+
+
Occlusion / bite
+
{{ $dentalVisitNote?->occlusion ?: '—' }}
+
+
+
Other notes
+
{{ $dentalVisitNote?->notes ?: '—' }}
+
+
+ @endif
diff --git a/resources/views/care/specialty/dentistry/workspace-odontogram.blade.php b/resources/views/care/specialty/dentistry/workspace-odontogram.blade.php index 319cb9e..0747449 100644 --- a/resources/views/care/specialty/dentistry/workspace-odontogram.blade.php +++ b/resources/views/care/specialty/dentistry/workspace-odontogram.blade.php @@ -3,24 +3,34 @@ $selected = old('tooth_code', request('tooth', ($dentalRows['upper'][0] ?? '16'))); $selectedData = $teethMap[$selected] ?? ['status' => 'present', 'surfaces' => [], 'conditions' => [], 'notes' => null]; $dentition = $dentalChart->dentition ?? 'adult'; + $canManage = $canManageSpecialty ?? true; @endphp

Odontogram (FDI)

-

Click a tooth to chart status, surfaces, and conditions.

+

+ {{ $canManage ? 'Click a tooth to chart status, surfaces, and conditions.' : 'View tooth chart status, surfaces, and conditions.' }} +

-
- @csrf - - -
+ @if ($canManage) +
+ @csrf + + +
+ @else +

+ Dentition: + {{ ($dentalDentitions ?? [])[$dentition] ?? $dentition }} +

+ @endif Print
@@ -60,51 +70,84 @@ @endforeach -
- @csrf - -
- -

{{ $selected }}

-
-
- - -
-
-

Surfaces

-
- @foreach ($dentalSurfaces as $surface) - - @endforeach + @if ($canManage) + + @csrf + +
+ +

{{ $selected }}

-
-
-

Conditions

-
- @foreach ($dentalConditions as $value => $label) - - @endforeach +
+ +
-
-
- - -
-
- -
- +
+

Surfaces

+
+ @foreach ($dentalSurfaces as $surface) + + @endforeach +
+
+
+

Conditions

+
+ @foreach ($dentalConditions as $value => $label) + + @endforeach +
+
+
+ + +
+
+ +
+ + @else +
+
+
Selected tooth
+
{{ $selected }}
+
+
+
Status
+
{{ ($dentalStatuses ?? [])[$selectedData['status'] ?? 'present'] ?? ($selectedData['status'] ?? '—') }}
+
+
+
Surfaces
+
{{ ! empty($selectedData['surfaces']) ? implode(', ', $selectedData['surfaces']) : '—' }}
+
+
+
Conditions
+
+ @php + $conditionLabels = collect($selectedData['conditions'] ?? []) + ->map(fn ($c) => ($dentalConditions ?? [])[$c] ?? $c) + ->filter() + ->all(); + @endphp + {{ $conditionLabels !== [] ? implode(', ', $conditionLabels) : '—' }} +
+
+
+
Notes
+
{{ $selectedData['notes'] ?: '—' }}
+
+
+ @endif
diff --git a/resources/views/care/specialty/dentistry/workspace-overview.blade.php b/resources/views/care/specialty/dentistry/workspace-overview.blade.php index 7272d3f..b600f9f 100644 --- a/resources/views/care/specialty/dentistry/workspace-overview.blade.php +++ b/resources/views/care/specialty/dentistry/workspace-overview.blade.php @@ -2,6 +2,7 @@ $plan = $dentalPlan; $openItems = $plan?->items?->whereIn('status', ['proposed', 'accepted']) ?? collect(); $currentStage = $workspaceVisit->specialty_stage; + $canManage = $canManageSpecialty ?? true; $stageFlow = [ 'waiting' => ['next' => 'chair', 'label' => 'Seat at chair'], 'chair' => ['next' => 'procedure', 'label' => 'Start procedure'], @@ -26,20 +27,33 @@

@foreach (['waiting', 'chair', 'procedure', 'recovery', 'completed'] as $stageCode) -
- @csrf - - +
+ @else + $currentStage === $stageCode, - 'border border-slate-200 bg-white text-slate-700 hover:bg-slate-50' => $currentStage !== $stageCode, - ])> + 'border border-slate-200 bg-white text-slate-400' => $currentStage !== $stageCode, + ]) + @if ($currentStage !== $stageCode) aria-disabled="true" title="View-only access" @endif + > {{ ucfirst($stageCode) }} - - + + @endif @endforeach - @if ($currentStage && isset($stageFlow[$currentStage])) + @if ($canManage && $currentStage && isset($stageFlow[$currentStage]))
@csrf diff --git a/resources/views/care/specialty/dentistry/workspace-perio.blade.php b/resources/views/care/specialty/dentistry/workspace-perio.blade.php index ef8fbd7..e633256 100644 --- a/resources/views/care/specialty/dentistry/workspace-perio.blade.php +++ b/resources/views/care/specialty/dentistry/workspace-perio.blade.php @@ -6,6 +6,7 @@ } $teeth = array_merge($dentalRows['upper'] ?? [], $dentalRows['lower'] ?? []); $probeTeeth = array_slice($teeth, 0, 8); + $canManage = $canManageSpecialty ?? true; @endphp
@@ -16,9 +17,58 @@

Latest exam {{ $exam->exam_date?->format('d M Y') }} · {{ $exam->sites->count() }} sites

@endif - - @csrf -
+ @if ($canManage) + + @csrf +
+ + + + + @foreach ($dentalPerioSurfaces ?? [] as $surface) + + + + @endforeach + + + + @foreach ($probeTeeth as $idx => $tooth) + + + @foreach ($dentalPerioSurfaces ?? [] as $sIdx => $surface) + @php + $existing = $siteMap[$tooth][$surface] ?? null; + @endphp + + + + + + @endforeach + + @endforeach + +
Tooth{{ $surface }} mmBP
{{ $tooth }} + + + bleeding)> + + plaque)> +
+
+
+ + +
+ + + @else +
@@ -31,39 +81,26 @@ - @foreach ($probeTeeth as $idx => $tooth) + @forelse ($probeTeeth as $tooth) - @foreach ($dentalPerioSurfaces ?? [] as $sIdx => $surface) - @php - $existing = $siteMap[$tooth][$surface] ?? null; - $base = "sites.{$idx}_{$sIdx}"; - @endphp - - - - - + @foreach ($dentalPerioSurfaces ?? [] as $surface) + @php $existing = $siteMap[$tooth][$surface] ?? null; @endphp + + + @endforeach - @endforeach + @empty + + + + @endforelse
{{ $tooth }} - - - bleeding)> - - plaque)> - {{ $existing?->probing_mm ?? '—' }}{{ $existing?->bleeding ? '✓' : '—' }}{{ $existing?->plaque ? '✓' : '—' }}
No perio exam yet.
-
- - -
- - + @if ($exam?->notes) +

{{ $exam->notes }}

+ @endif + @endif
diff --git a/resources/views/care/specialty/dentistry/workspace-plan.blade.php b/resources/views/care/specialty/dentistry/workspace-plan.blade.php index 37bd4d4..e30d054 100644 --- a/resources/views/care/specialty/dentistry/workspace-plan.blade.php +++ b/resources/views/care/specialty/dentistry/workspace-plan.blade.php @@ -1,6 +1,7 @@ @php $plan = $dentalPlan; $history = ($dentalPlanHistory ?? collect())->filter(fn ($p) => ! $plan || $p->id !== $plan->id); + $canManage = $canManageSpecialty ?? true; @endphp
@@ -16,7 +17,7 @@ @endif

- @if ($plan) + @if ($canManage && $plan)
@if ($plan->status === 'draft')
@@ -53,14 +54,14 @@

Priority {{ $item->priority }} · {{ ucfirst($item->status) }} · {{ number_format($item->estimate_minor / 100, 2) }}

- @if (! in_array($item->status, ['done', 'cancelled'], true)) + @if ($canManage && ! in_array($item->status, ['done', 'cancelled'], true)) @csrf @endif - @if (! in_array($item->status, ['done', 'cancelled'], true)) + @if ($canManage && ! in_array($item->status, ['done', 'cancelled'], true))
@csrf + @if ($canManage) + + @csrf +

Schedule recall

+
+
+ + +
+
+ + +
+
+ + +
-
- - -
-
- - -
- - -
+ + + @endif
diff --git a/resources/views/care/specialty/dentistry/workspace-treat.blade.php b/resources/views/care/specialty/dentistry/workspace-treat.blade.php index 390c5ca..83f7354 100644 --- a/resources/views/care/specialty/dentistry/workspace-treat.blade.php +++ b/resources/views/care/specialty/dentistry/workspace-treat.blade.php @@ -1,8 +1,12 @@ +@php $canManage = $canManageSpecialty ?? true; @endphp +

Treat today

-

Record a completed procedure. It posts to the visit bill automatically.

+

+ {{ $canManage ? 'Record a completed procedure. It posts to the visit bill automatically.' : 'Completed procedures for this visit.' }} +

- @if ($dentalPlan?->items) + @if ($canManage && $dentalPlan?->items)

From plan

+ @elseif (! $canManage && $dentalPlan?->items?->whereIn('status', ['proposed', 'accepted'])->isNotEmpty()) +
+

Open plan items

+ +
@endif -
- @csrf -

Ad-hoc procedure

- -
-
- - -
-
- - -
-
- - -
-
-

Surfaces

-
- @foreach ($dentalSurfaces as $surface) - - @endforeach + @if ($canManage) + + @csrf +

Ad-hoc procedure

+ +
+
+ + +
+
+ + +
+
+ + +
+
+

Surfaces

+
+ @foreach ($dentalSurfaces as $surface) + + @endforeach +
+
+
+ +
-
- - -
-
- - + + + @endif

Completed this visit

diff --git a/resources/views/care/specialty/emergency/workspace-disposition.blade.php b/resources/views/care/specialty/emergency/workspace-disposition.blade.php index 543c0b9..a46affb 100644 --- a/resources/views/care/specialty/emergency/workspace-disposition.blade.php +++ b/resources/views/care/specialty/emergency/workspace-disposition.blade.php @@ -1,6 +1,7 @@ @php $record = $emergencyDisposition; $payload = old('payload', $record?->payload ?? []); + $canManage = $canManageSpecialty ?? true; @endphp
@@ -12,57 +13,94 @@ Print summary
-
- @csrf - + @if ($canManage) + + @csrf + -
-
- - - @error('payload.disposition')

{{ $message }}

@enderror +
+
+ + + @error('payload.disposition')

{{ $message }}

@enderror +
+
+ + +
+
+ + +
+
+ + +
+
+ + + @error('payload.diagnosis')

{{ $message }}

@enderror +
+
+ + +
+
+ + +
+
+ + +
-
- - -
-
- - -
-
- - -
-
- - - @error('payload.diagnosis')

{{ $message }}

@enderror -
-
- - -
-
- - -
-
- - -
-
- - + + + @else +
+
+
Final disposition
+
{{ $payload['disposition'] ?? '—' }}
+
+
+
Condition
+
{{ $payload['condition'] ?? '—' }}
+
+
+
Destination
+
{{ $payload['destination'] ?? '—' }}
+
+
+
Disposition time
+
{{ $payload['time'] ?? '—' }}
+
+
+
Diagnosis
+
{{ $payload['diagnosis'] ?? '—' }}
+
+
+
Advice / follow-up
+
{{ $payload['advice'] ?? '—' }}
+
+
+
Medications on discharge
+
{{ $payload['medications'] ?? '—' }}
+
+
+
Notes
+
{{ $payload['notes'] ?? '—' }}
+
+
+ @endif
diff --git a/resources/views/care/specialty/emergency/workspace-overview.blade.php b/resources/views/care/specialty/emergency/workspace-overview.blade.php index da205ed..9c7d910 100644 --- a/resources/views/care/specialty/emergency/workspace-overview.blade.php +++ b/resources/views/care/specialty/emergency/workspace-overview.blade.php @@ -4,6 +4,7 @@ $currentStage = $workspaceVisit->specialty_stage; $stageFlow = $emergencyStageFlow ?? []; $latest = $emergencyLatestVitals; + $canManage = $canManageSpecialty ?? true; @endphp
@@ -55,20 +56,33 @@

@foreach (($emergencyStageCodes ?: ['arrival', 'resus', 'treatment', 'observation', 'disposition']) as $stageCode) -
- @csrf - - +
+ @else + $currentStage === $stageCode, - 'border border-slate-200 bg-white text-slate-700 hover:bg-slate-50' => $currentStage !== $stageCode, - ])> + 'border border-slate-200 bg-white text-slate-400' => $currentStage !== $stageCode, + ]) + @if ($currentStage !== $stageCode) aria-disabled="true" title="View-only access" @endif + > {{ ucfirst(str_replace('_', ' ', $stageCode)) }} - - + + @endif @endforeach - @if ($currentStage && isset($stageFlow[$currentStage]) && $stageFlow[$currentStage]['next'] !== $currentStage) + @if ($canManage && $currentStage && isset($stageFlow[$currentStage]) && $stageFlow[$currentStage]['next'] !== $currentStage)
@csrf diff --git a/resources/views/care/specialty/emergency/workspace-vitals.blade.php b/resources/views/care/specialty/emergency/workspace-vitals.blade.php index f9617c4..a935731 100644 --- a/resources/views/care/specialty/emergency/workspace-vitals.blade.php +++ b/resources/views/care/specialty/emergency/workspace-vitals.blade.php @@ -1,3 +1,5 @@ +@php $canManage = $canManageSpecialty ?? true; @endphp +
@@ -6,46 +8,48 @@
- - @csrf -
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
- + @if ($canManage) +
+ @csrf +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ @endif -
+
$canManage, 'mt-4' => ! $canManage])>

History

    @forelse ($emergencyVitals as $row) diff --git a/resources/views/care/specialty/partials/actions-menu.blade.php b/resources/views/care/specialty/partials/actions-menu.blade.php index 4ca321c..014c4f9 100644 --- a/resources/views/care/specialty/partials/actions-menu.blade.php +++ b/resources/views/care/specialty/partials/actions-menu.blade.php @@ -40,7 +40,7 @@ $currentStage = $workspaceVisit?->specialty_stage; @endphp -@if ($onWorkspace) +@if ($onWorkspace && ($canManageSpecialty ?? true)) @include('care.partials.queue-ops', [ 'queueIntegration' => $queueIntegration ?? null, 'queueCallNextRoute' => 'care.specialty.call-next', @@ -50,7 +50,7 @@ ]) @endif -@if ($ticketCalled && $appointment) +@if (($canManageSpecialty ?? true) && $ticketCalled && $appointment)
    @csrf diff --git a/resources/views/care/specialty/sections/workspace.blade.php b/resources/views/care/specialty/sections/workspace.blade.php index 26f9dfc..2e59196 100644 --- a/resources/views/care/specialty/sections/workspace.blade.php +++ b/resources/views/care/specialty/sections/workspace.blade.php @@ -42,22 +42,26 @@ @include('care.specialty.emergency.workspace-'.$activeTab) @elseif ($activeTab === 'billing')
    -

    Add specialty service

    - - @csrf - - - +

    + {{ ($canManageSpecialty ?? true) ? 'Add specialty service' : 'Visit billing' }} +

    + @if ($canManageSpecialty ?? true) +
    + @csrf + + +
    + @endif @if ($workspaceVisit->bill) -
    +
    ($canManageSpecialty ?? true), 'mt-3' => ! ($canManageSpecialty ?? true)])>

    Current invoice {{ $workspaceVisit->bill->invoice_number }}

      @forelse ($workspaceVisit->bill->lineItems as $line) @@ -71,6 +75,8 @@
    Open bill
    + @elseif (! ($canManageSpecialty ?? true)) +

    No invoice on this visit yet.

    @endif
    @elseif (! empty($clinicalFields)) @@ -82,11 +88,13 @@

    Documents

    Specialty documents attach to the patient chart for this episode.

    -
    - @csrf - - -
    + @if ($canManageSpecialty ?? true) +
    + @csrf + + +
    + @endif
      @forelse ($visitDocuments ?? [] as $doc) diff --git a/resources/views/care/specialty/shell.blade.php b/resources/views/care/specialty/shell.blade.php index 7e6bb58..6bcdea9 100644 --- a/resources/views/care/specialty/shell.blade.php +++ b/resources/views/care/specialty/shell.blade.php @@ -116,7 +116,9 @@
      History - Billing + @if ($canManageSpecialty ?? true) + Billing + @endif
      @include('care.partials.queue-board', [ @@ -128,7 +130,7 @@ 'canConsult' => $canConsult ?? false, 'lockToPractitioner' => $lockToPractitioner ?? false, 'showFilters' => true, - 'queueCallNextRoute' => 'care.specialty.call-next', + 'queueCallNextRoute' => ($canManageSpecialty ?? true) ? 'care.specialty.call-next' : null, 'queueCallNextParams' => ['module' => $moduleKey], 'startRouteName' => 'care.queue.start', 'inCareLabel' => 'In care', diff --git a/tests/Feature/CareSpecialtyAccessTest.php b/tests/Feature/CareSpecialtyAccessTest.php index 0d958af..eba4859 100644 --- a/tests/Feature/CareSpecialtyAccessTest.php +++ b/tests/Feature/CareSpecialtyAccessTest.php @@ -235,9 +235,18 @@ class CareSpecialtyAccessTest extends TestCase ]); $this->actingAs($doctor) - ->get(route('care.specialty.workspace', ['module' => 'cardiology', 'visit' => $visit])) + ->get(route('care.specialty.workspace', ['module' => 'cardiology', 'visit' => $visit, 'tab' => 'exam'])) ->assertOk() - ->assertSee('view + refer'); + ->assertSee('view + refer') + ->assertDontSee('Save record') + ->assertDontSee('Call next') + ->assertDontSee('Add to invoice') + ->assertDontSee('Upload document') + ->assertSee('Refer to specialty queue') + ->assertDontSee( + 'action="'.route('care.specialty.consultation.start', ['module' => 'cardiology', 'visit' => $visit], false).'"', + false, + ); $this->actingAs($doctor) ->post(route('care.specialty.clinical.save', ['module' => 'cardiology', 'visit' => $visit]), [ @@ -249,6 +258,82 @@ class CareSpecialtyAccessTest extends TestCase ->assertForbidden(); } + public function test_sidebar_and_dashboard_exclude_modules_with_no_access(): void + { + [$pharmacistUser, $pharmacistMember] = $this->makeStaff('pharmacist', 'rx-nav'); + + $enabledForMember = collect($this->modules->enabledModulesForMember($this->organization, $pharmacistMember)) + ->pluck('key') + ->all(); + + $this->assertContains('emergency', $enabledForMember); + $this->assertContains('infusion', $enabledForMember); + $this->assertNotContains('cardiology', $enabledForMember); + $this->assertNotContains('dentistry', $enabledForMember); + + $this->actingAs($pharmacistUser) + ->get(route('care.dashboard')) + ->assertOk() + ->assertSee('Emergency') + ->assertDontSee('Cardiology'); + } + + public function test_manage_role_still_sees_mutate_actions_on_restricted_module(): void + { + [$doctor, $member] = $this->makeStaff('doctor', 'cardio-ui'); + $dept = Department::query()->where('type', 'cardiology')->firstOrFail(); + Practitioner::create([ + 'owner_ref' => $this->owner->public_id, + 'organization_id' => $this->organization->id, + 'branch_id' => $this->branch->id, + 'department_id' => $dept->id, + 'member_id' => $member->id, + 'user_ref' => $doctor->public_id, + 'name' => 'Dr Cardio UI', + 'specialty' => 'Cardiology', + 'is_active' => true, + ]); + + $patient = Patient::create([ + 'owner_ref' => $this->owner->public_id, + 'organization_id' => $this->organization->id, + 'branch_id' => $this->branch->id, + 'patient_number' => 'P-CARD-UI', + 'first_name' => 'Abena', + 'last_name' => 'Heart', + 'gender' => 'female', + 'date_of_birth' => '1985-01-01', + ]); + $visit = \App\Models\Visit::create([ + 'owner_ref' => $this->owner->public_id, + 'organization_id' => $this->organization->id, + 'branch_id' => $this->branch->id, + 'patient_id' => $patient->id, + 'status' => \App\Models\Visit::STATUS_IN_PROGRESS, + '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' => $dept->id, + 'visit_id' => $visit->id, + 'type' => Appointment::TYPE_WALK_IN, + 'status' => Appointment::STATUS_WAITING, + 'scheduled_at' => now(), + 'checked_in_at' => now(), + ]); + + $this->assertTrue($this->modules->memberCanManage($this->organization, $member, 'cardiology')); + + $this->actingAs($doctor) + ->get(route('care.specialty.workspace', ['module' => 'cardiology', 'visit' => $visit])) + ->assertOk() + ->assertDontSee('view + refer') + ->assertSee('Start'); + } + public function test_admin_keeps_full_manage_access(): void { $admin = Member::query()->where('user_ref', $this->owner->public_id)->firstOrFail();