diff --git a/app/Http/Controllers/Care/PrescriptionController.php b/app/Http/Controllers/Care/PrescriptionController.php index 98036f9..0e989e8 100644 --- a/app/Http/Controllers/Care/PrescriptionController.php +++ b/app/Http/Controllers/Care/PrescriptionController.php @@ -193,6 +193,30 @@ class PrescriptionController extends Controller ->with('success', 'Prescription created.'); } + if ($request->input('return_to') === 'specialty') { + $module = (string) $request->input('specialty_module', ''); + $visitId = (int) $request->input('specialty_visit_id', 0); + $modules = app(\App\Services\Care\SpecialtyModuleService::class); + $visit = $consultation->visit_id + ? \App\Models\Visit::query()->find($consultation->visit_id) + : null; + + if ( + $module !== '' + && $modules->definition($module) + && $visit + && (int) $visit->id === $visitId + && (int) $visit->id === (int) $consultation->visit_id + ) { + return redirect() + ->route('care.specialty.workspace', [ + 'module' => $module, + 'visit' => $visit, + ]) + ->with('success', 'Prescription created.'); + } + } + return redirect()->route('care.prescriptions.show', array_filter([ 'prescription' => $prescription, ...$return->query($consultation), diff --git a/app/Http/Controllers/Care/SpecialtyModuleController.php b/app/Http/Controllers/Care/SpecialtyModuleController.php index 29aa813..6fdde2d 100644 --- a/app/Http/Controllers/Care/SpecialtyModuleController.php +++ b/app/Http/Controllers/Care/SpecialtyModuleController.php @@ -829,6 +829,8 @@ class SpecialtyModuleController extends Controller && $canManageSpecialty && $permissions->can($member, 'blood_bank.manage')); $canStartConsultation = $canConsult; + // Same ability as GP consultation chart — not consultations.manage alone. + $canPrescribe = $permissions->can($member, 'prescriptions.manage') && $canManageSpecialty; $canCallNext = $canManageSpecialty; $canManageClinical = $canManageSpecialty; $canManageVitals = $canManageSpecialty && ( @@ -1176,6 +1178,7 @@ class SpecialtyModuleController extends Controller 'canConsult' => $canConsult, 'canAdvanceStage' => $canAdvanceStage, 'canStartConsultation' => $canStartConsultation, + 'canPrescribe' => $canPrescribe, 'canCallNext' => $canCallNext, 'canManageClinical' => $canManageClinical, 'canManageVitals' => $canManageVitals, diff --git a/resources/views/care/prescriptions/partials/form.blade.php b/resources/views/care/prescriptions/partials/form.blade.php index 9fbab6b..e98c781 100644 --- a/resources/views/care/prescriptions/partials/form.blade.php +++ b/resources/views/care/prescriptions/partials/form.blade.php @@ -1,7 +1,8 @@ -{{-- Shared prescription line-item form body (create page + consultation modal). --}} +{{-- Shared prescription line-item form body (create page + consultation / specialty modal). --}} @php $routes = $routes ?? config('care.medication_routes', []); $compact = $compact ?? false; + $returnTo = $returnTo ?? ($compact ? 'consultation' : null); @endphp
- @if ($compact) - + @if ($returnTo) + + @if ($returnTo === 'specialty' && ! empty($specialtyModule) && ! empty($specialtyVisit)) + + + @endif @endif
$compact, 'flex gap-3' => ! $compact])> diff --git a/resources/views/care/specialty/partials/actions-menu.blade.php b/resources/views/care/specialty/partials/actions-menu.blade.php index a3b6c7c..6e5a3d8 100644 --- a/resources/views/care/specialty/partials/actions-menu.blade.php +++ b/resources/views/care/specialty/partials/actions-menu.blade.php @@ -6,12 +6,14 @@ $btnAccent = $btn.' border border-indigo-200 bg-indigo-50 text-indigo-900 hover:bg-indigo-100'; $onWorkspace = ($section ?? '') === 'workspace'; $appointment = $workspaceVisit?->appointment; - $openConsultation = $appointment?->consultation; + $openConsultation = $appointment?->consultation + ?? $workspaceVisit?->consultations?->firstWhere('status', '!=', \App\Models\Consultation::STATUS_COMPLETED); $ticketCalled = $appointment && $appointment->queue_ticket_status === 'called'; $canCallNext = $canCallNext ?? ($canManageSpecialty ?? false); $canConsult = $canConsult ?? false; $canAdvanceStage = $canAdvanceStage ?? $canConsult; $canStartConsultationFlag = $canStartConsultation ?? $canConsult; + $canPrescribe = $canPrescribe ?? false; $canBookAppointments = $canBookAppointments ?? false; $canViewPatients = $canViewPatients ?? true; $canViewAppointments = $canViewAppointments ?? true; @@ -102,6 +104,16 @@ @endif + @if ($canPrescribe && $openConsultation && $openConsultation->status !== \App\Models\Consultation::STATUS_COMPLETED) + + @endif + @if ($consultationInProgress) diff --git a/resources/views/care/specialty/shell.blade.php b/resources/views/care/specialty/shell.blade.php index 6397f4f..689f4d2 100644 --- a/resources/views/care/specialty/shell.blade.php +++ b/resources/views/care/specialty/shell.blade.php @@ -80,7 +80,12 @@ @php $completeConsultation = ($canConsult ?? false) - ? $workspaceVisit?->appointment?->consultation + ? ($workspaceVisit?->appointment?->consultation + ?? $workspaceVisit?->consultations?->firstWhere('status', '!=', \App\Models\Consultation::STATUS_COMPLETED)) + : null; + $prescribeConsultation = ($canPrescribe ?? false) + ? ($workspaceVisit?->appointment?->consultation + ?? $workspaceVisit?->consultations?->firstWhere('status', '!=', \App\Models\Consultation::STATUS_COMPLETED)) : null; @endphp @if ($completeConsultation && $completeConsultation->status !== \App\Models\Consultation::STATUS_COMPLETED) @@ -93,6 +98,29 @@ variant="primary" /> @endif + @if ($prescribeConsultation && $prescribeConsultation->status !== \App\Models\Consultation::STATUS_COMPLETED) + +
+

New prescription

+

+ {{ ($workspaceVisit->patient ?? $prescribeConsultation->patient)?->fullName() }} + @if (($workspaceVisit->patient ?? $prescribeConsultation->patient)?->patient_number) + ({{ ($workspaceVisit->patient ?? $prescribeConsultation->patient)->patient_number }}) + @endif +

+
+ @include('care.prescriptions.partials.form', [ + 'consultation' => $prescribeConsultation, + 'routes' => config('care.medication_routes'), + 'compact' => true, + 'returnTo' => 'specialty', + 'specialtyModule' => $moduleKey, + 'specialtyVisit' => $workspaceVisit, + ]) +
+
+
+ @endif @elseif ($section === 'history')
diff --git a/tests/Feature/CareSpecialtyAccessTest.php b/tests/Feature/CareSpecialtyAccessTest.php index a60618e..a60ef7d 100644 --- a/tests/Feature/CareSpecialtyAccessTest.php +++ b/tests/Feature/CareSpecialtyAccessTest.php @@ -5,6 +5,7 @@ namespace Tests\Feature; use App\Http\Middleware\EnsurePlatformSession; use App\Models\Appointment; use App\Models\Branch; +use App\Models\Consultation; use App\Models\Department; use App\Models\Member; use App\Models\Organization; @@ -864,4 +865,126 @@ class CareSpecialtyAccessTest extends TestCase ->post(route('care.specialty.emergency.stage', $visit), ['stage' => 'treatment']) ->assertForbidden(); } + + public function test_doctor_with_prescriptions_manage_sees_prescribe_on_specialty_workspace(): void + { + [$doctorUser, $doctorMember, $visit] = $this->dentistryVisitForRole('doctor', 'den-rx'); + $appointment = $visit->appointment()->firstOrFail(); + $appointment->update([ + 'status' => Appointment::STATUS_IN_CONSULTATION, + 'started_at' => now(), + 'queue_ticket_status' => 'serving', + ]); + $consultation = Consultation::create([ + 'owner_ref' => $this->owner->public_id, + 'visit_id' => $visit->id, + 'appointment_id' => $appointment->id, + 'patient_id' => $visit->patient_id, + 'status' => Consultation::STATUS_DRAFT, + 'started_at' => now(), + ]); + + $permissions = app(\App\Services\Care\CarePermissions::class); + $this->assertTrue($permissions->can($doctorMember, 'prescriptions.manage')); + $this->assertTrue($this->modules->memberCanManage($this->organization, $doctorMember, 'dentistry')); + + $html = $this->actingAs($doctorUser) + ->get(route('care.specialty.workspace', [ + 'module' => 'dentistry', + 'visit' => $visit, + 'tab' => 'overview', + ])) + ->assertOk() + ->assertSee('Prescribe') + ->assertSee('New prescription') + ->getContent(); + + $this->assertStringContainsString( + route('care.prescriptions.store', $consultation, absolute: false), + $html, + ); + $this->assertStringContainsString('name="return_to" value="specialty"', $html); + $this->assertStringContainsString('name="specialty_module" value="dentistry"', $html); + } + + public function test_nurse_without_prescriptions_manage_does_not_see_prescribe_cta(): void + { + [$nurseUser, $nurseMember, $visit] = $this->dentistryVisitForRole('nurse', 'den-no-rx'); + $appointment = $visit->appointment()->firstOrFail(); + $appointment->update([ + 'status' => Appointment::STATUS_IN_CONSULTATION, + 'started_at' => now(), + 'queue_ticket_status' => 'serving', + ]); + Consultation::create([ + 'owner_ref' => $this->owner->public_id, + 'visit_id' => $visit->id, + 'appointment_id' => $appointment->id, + 'patient_id' => $visit->patient_id, + 'status' => Consultation::STATUS_DRAFT, + 'started_at' => now(), + ]); + + $permissions = app(\App\Services\Care\CarePermissions::class); + $this->assertTrue($this->modules->memberCanManage($this->organization, $nurseMember, 'dentistry')); + $this->assertFalse($permissions->can($nurseMember, 'prescriptions.manage')); + + $this->actingAs($nurseUser) + ->get(route('care.specialty.workspace', [ + 'module' => 'dentistry', + 'visit' => $visit, + 'tab' => 'overview', + ])) + ->assertOk() + ->assertDontSee('Prescribe') + ->assertDontSee('New prescription') + ->assertDontSee(route('care.prescriptions.store', Consultation::query()->where('visit_id', $visit->id)->first(), absolute: false)); + } + + public function test_specialty_prescribe_store_returns_to_workspace(): void + { + [$doctorUser, , $visit] = $this->dentistryVisitForRole('doctor', 'den-rx-store'); + $appointment = $visit->appointment()->firstOrFail(); + $appointment->update([ + 'status' => Appointment::STATUS_IN_CONSULTATION, + 'started_at' => now(), + 'queue_ticket_status' => 'serving', + ]); + $consultation = Consultation::create([ + 'owner_ref' => $this->owner->public_id, + 'visit_id' => $visit->id, + 'appointment_id' => $appointment->id, + 'patient_id' => $visit->patient_id, + 'status' => Consultation::STATUS_DRAFT, + 'started_at' => now(), + ]); + + $this->actingAs($doctorUser) + ->post(route('care.prescriptions.store', $consultation), [ + 'activate' => true, + 'return_to' => 'specialty', + 'specialty_module' => 'dentistry', + 'specialty_visit_id' => $visit->id, + 'from_consultation' => $consultation->uuid, + 'items' => [ + [ + 'name' => 'Amoxicillin 500mg', + 'dosage' => '1 capsule', + 'frequency' => 'TDS', + 'duration' => '5 days', + 'route' => 'oral', + ], + ], + ]) + ->assertRedirect(route('care.specialty.workspace', [ + 'module' => 'dentistry', + 'visit' => $visit, + ])); + + $this->assertDatabaseHas('care_prescriptions', [ + 'consultation_id' => $consultation->id, + 'visit_id' => $visit->id, + 'patient_id' => $visit->patient_id, + ]); + } }