diff --git a/app/Http/Controllers/Api/PatientController.php b/app/Http/Controllers/Api/PatientController.php index 4ecabea..0984e27 100644 --- a/app/Http/Controllers/Api/PatientController.php +++ b/app/Http/Controllers/Api/PatientController.php @@ -4,7 +4,9 @@ namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Http\Controllers\Api\Concerns\ScopesApiToAccount; +use App\Models\Appointment; use App\Models\Patient; +use App\Models\Visit; use App\Services\Care\CarePermissions; use App\Services\Care\OrganizationResolver; use App\Services\Care\PatientService; @@ -89,9 +91,22 @@ class PatientController extends Controller abort_unless($patient->organization_id === $this->organization($request)->id, 404); $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request)); - if ($branchScope !== null && $patient->branch_id !== $branchScope) { - abort(404); + if ($branchScope === null || $patient->branch_id === $branchScope) { + return; } + + $hasLocalActivity = Visit::query() + ->where('patient_id', $patient->id) + ->where('organization_id', $patient->organization_id) + ->where('branch_id', $branchScope) + ->exists() + || Appointment::query() + ->where('patient_id', $patient->id) + ->where('organization_id', $patient->organization_id) + ->where('branch_id', $branchScope) + ->exists(); + + abort_unless($hasLocalActivity, 404); } /** diff --git a/app/Http/Controllers/Care/PatientController.php b/app/Http/Controllers/Care/PatientController.php index 9fb3ab6..06463ce 100644 --- a/app/Http/Controllers/Care/PatientController.php +++ b/app/Http/Controllers/Care/PatientController.php @@ -4,8 +4,10 @@ namespace App\Http\Controllers\Care; use App\Http\Controllers\Controller; use App\Http\Controllers\Care\Concerns\ScopesToAccount; +use App\Models\Appointment; use App\Models\Branch; use App\Models\Patient; +use App\Models\Visit; use App\Services\Care\AdminOverviewService; use App\Services\Care\CareFeatures; use App\Services\Care\CarePermissions; @@ -293,9 +295,24 @@ class PatientController extends Controller abort_unless($patient->organization_id === $this->organization($request)->id, 404); $branchId = app(OrganizationResolver::class)->branchScope($this->member($request)); - if ($branchId !== null && $patient->branch_id !== $branchId) { - abort(404); + if ($branchId === null || $patient->branch_id === $branchId) { + return; } + + // Home branch may differ from the site where care is delivered — allow chart + // access when the patient has a visit or appointment at the member's branch. + $hasLocalActivity = Visit::query() + ->where('patient_id', $patient->id) + ->where('organization_id', $patient->organization_id) + ->where('branch_id', $branchId) + ->exists() + || Appointment::query() + ->where('patient_id', $patient->id) + ->where('organization_id', $patient->organization_id) + ->where('branch_id', $branchId) + ->exists(); + + abort_unless($hasLocalActivity, 404); } /** diff --git a/app/Http/Controllers/Care/PatientMessageController.php b/app/Http/Controllers/Care/PatientMessageController.php index 0aa370d..9493489 100644 --- a/app/Http/Controllers/Care/PatientMessageController.php +++ b/app/Http/Controllers/Care/PatientMessageController.php @@ -4,7 +4,9 @@ namespace App\Http\Controllers\Care; use App\Http\Controllers\Controller; use App\Http\Controllers\Care\Concerns\ScopesToAccount; +use App\Models\Appointment; use App\Models\Patient; +use App\Models\Visit; use App\Services\Billing\PlatformEmailClient; use App\Services\Billing\PlatformSmsClient; use App\Services\Care\AuditLogger; @@ -176,8 +178,21 @@ class PatientMessageController extends Controller abort_unless($patient->organization_id === $this->organization($request)->id, 404); $branchId = app(OrganizationResolver::class)->branchScope($this->member($request)); - if ($branchId !== null && $patient->branch_id !== $branchId) { - abort(404); + if ($branchId === null || $patient->branch_id === $branchId) { + return; } + + $hasLocalActivity = Visit::query() + ->where('patient_id', $patient->id) + ->where('organization_id', $patient->organization_id) + ->where('branch_id', $branchId) + ->exists() + || Appointment::query() + ->where('patient_id', $patient->id) + ->where('organization_id', $patient->organization_id) + ->where('branch_id', $branchId) + ->exists(); + + abort_unless($hasLocalActivity, 404); } } diff --git a/app/Http/Controllers/Care/SpecialtyModuleController.php b/app/Http/Controllers/Care/SpecialtyModuleController.php index d527294..5558e79 100644 --- a/app/Http/Controllers/Care/SpecialtyModuleController.php +++ b/app/Http/Controllers/Care/SpecialtyModuleController.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Care\Concerns\ScopesToAccount; use App\Http\Controllers\Controller; use App\Models\Appointment; use App\Models\Department; +use App\Models\InvestigationType; use App\Models\PatientAttachment; use App\Models\Visit; use App\Services\Care\AppointmentService; @@ -507,6 +508,7 @@ class SpecialtyModuleController extends Controller $clinicalFields = []; $clinicalAlerts = []; $visitDocuments = collect(); + $investigationTypes = collect(); $dentalChart = null; $dentalTeethMap = []; $dentalPlan = null; @@ -529,9 +531,9 @@ class SpecialtyModuleController extends Controller 'patient.emergencyContacts', 'patient.attachments', 'appointment.practitioner', - 'appointment.consultation', + 'appointment.consultation.investigationRequests.investigationType', 'bill.lineItems', - 'consultations', + 'consultations.investigationRequests.investigationType', ]); $workspaceVisit = $visit; if ($visit->patient) { @@ -549,9 +551,9 @@ class SpecialtyModuleController extends Controller 'patient.emergencyContacts', 'patient.attachments', 'appointment.practitioner', - 'appointment.consultation', + 'appointment.consultation.investigationRequests.investigationType', 'bill.lineItems', - 'consultations', + 'consultations.investigationRequests.investigationType', ]); $workspaceVisit = $first; $patientHeader = array_merge( @@ -624,6 +626,14 @@ class SpecialtyModuleController extends Controller ->limit(20) ->get() : collect(); + + if ($activeTab === 'orders' && $canConsult) { + $investigationTypes = InvestigationType::query() + ->where('organization_id', $organization->id) + ->where('is_active', true) + ->orderBy('name') + ->get(); + } } return view('care.specialty.shell', [ @@ -650,6 +660,7 @@ class SpecialtyModuleController extends Controller 'clinicalFields' => $clinicalFields, 'clinicalAlerts' => $clinicalAlerts, 'visitDocuments' => $visitDocuments, + 'investigationTypes' => $investigationTypes, 'dentalChart' => $dentalChart, 'dentalTeethMap' => $dentalTeethMap, 'dentalPlan' => $dentalPlan, diff --git a/app/Services/Care/CarePermissions.php b/app/Services/Care/CarePermissions.php index e9cc23e..2ea6ff2 100644 --- a/app/Services/Care/CarePermissions.php +++ b/app/Services/Care/CarePermissions.php @@ -18,7 +18,8 @@ class CarePermissions 'doctor' => [ 'dashboard.view', 'patients.view', 'appointments.view', 'consultations.view', 'consultations.manage', - 'investigations.request', 'prescriptions.manage', 'lab.results.view', + 'investigations.request', 'prescriptions.manage', + 'lab.view', 'lab.results.view', 'assessments.view', 'assessments.capture', 'assessments.manage', 'pathways.manage', 'service_queues.console', diff --git a/resources/views/care/specialty/partials/orders.blade.php b/resources/views/care/specialty/partials/orders.blade.php new file mode 100644 index 0000000..0491631 --- /dev/null +++ b/resources/views/care/specialty/partials/orders.blade.php @@ -0,0 +1,88 @@ +@php + $openConsultation = $workspaceVisit->appointment?->consultation + ?? $workspaceVisit->consultations->firstWhere('status', '!=', \App\Models\Consultation::STATUS_COMPLETED); + $canRequestLabs = ($canConsult ?? false) && $openConsultation; + $visitLabRequests = $workspaceVisit->consultations + ->flatMap(fn ($c) => $c->investigationRequests) + ->sortByDesc('id') + ->values(); +@endphp + +
+
+
+

Orders

+

Lab and imaging requests for this visit.

+
+ @if ($canRequestLabs) + + @endif +
+ + @if (! $openConsultation) +

Start the encounter to order lab / imaging from this visit.

+ @endif + + + +
+ @if ($workspaceVisit->appointment) + Appointment + @endif +
+
+ +@if ($canRequestLabs && ($investigationTypes ?? collect())->isNotEmpty()) + +
+

Request investigations

+

Select tests to send to the lab for this visit.

+
+ @csrf +
+ @foreach ($investigationTypes as $type) + + @endforeach +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+@endif diff --git a/resources/views/care/specialty/sections/workspace.blade.php b/resources/views/care/specialty/sections/workspace.blade.php index c6c54ff..1ec13e4 100644 --- a/resources/views/care/specialty/sections/workspace.blade.php +++ b/resources/views/care/specialty/sections/workspace.blade.php @@ -74,16 +74,7 @@ @elseif (! empty($clinicalFields)) @include('care.specialty.partials.clinical-form') @elseif ($activeTab === 'orders') -
-

Orders

-

Order lab / imaging from the consultation flow. Specialty order sets can extend this later.

-
- Lab requests - @if ($workspaceVisit->appointment) - Appointment - @endif -
-
+ @include('care.specialty.partials.orders') @elseif ($activeTab === 'documents')

Documents