authorizeAbility($request, 'consultations.view'); $this->authorizeConsultation($request, $consultation); $consultation->load([ 'patient', 'practitioner', 'visit', 'appointment', 'vitalSigns', 'diagnoses', 'documents', 'investigationRequests.investigationType', 'prescriptions.items', ]); $canManage = app(\App\Services\Care\CarePermissions::class) ->can($this->member($request), 'consultations.manage'); $canVitals = app(\App\Services\Care\CarePermissions::class) ->can($this->member($request), 'vitals.manage'); $canRequestInvestigations = app(\App\Services\Care\CarePermissions::class) ->can($this->member($request), 'investigations.request'); $canPrescribe = app(\App\Services\Care\CarePermissions::class) ->can($this->member($request), 'prescriptions.manage'); $canGenerateBill = app(\App\Services\Care\CarePermissions::class) ->can($this->member($request), 'bills.manage'); $practitioners = Practitioner::owned($this->ownerRef($request)) ->where('organization_id', $this->organization($request)->id) ->where('is_active', true) ->orderBy('name') ->get(); $investigationTypes = InvestigationType::owned($this->ownerRef($request)) ->where('organization_id', $this->organization($request)->id) ->where('is_active', true) ->orderBy('name') ->get(); return view('care.consultations.show', [ 'consultation' => $consultation, 'practitioners' => $practitioners, 'investigationTypes' => $investigationTypes, 'canManage' => $canManage, 'canVitals' => $canVitals, 'canRequestInvestigations' => $canRequestInvestigations, 'canPrescribe' => $canPrescribe, 'canGenerateBill' => $canGenerateBill, 'isCompleted' => $consultation->status === Consultation::STATUS_COMPLETED, ]); } public function update(Request $request, Consultation $consultation): RedirectResponse { $canManage = app(\App\Services\Care\CarePermissions::class) ->can($this->member($request), 'consultations.manage'); $canVitals = app(\App\Services\Care\CarePermissions::class) ->can($this->member($request), 'vitals.manage'); abort_unless($canManage || $canVitals, 403); $this->authorizeConsultation($request, $consultation); abort_if($consultation->status === Consultation::STATUS_COMPLETED, 422); $validated = $this->validatedConsultationData($request, $canManage, $canVitals); $this->consultations->save( $consultation, $this->ownerRef($request), $validated, $this->ownerRef($request), ); return back()->with('success', 'Consultation saved.'); } public function complete(Request $request, Consultation $consultation): RedirectResponse { $this->authorizeAbility($request, 'consultations.manage'); $this->authorizeConsultation($request, $consultation); $this->consultations->complete( $consultation, $this->ownerRef($request), $this->ownerRef($request), ); return redirect()->route('care.patients.show', $consultation->patient) ->with('success', 'Consultation completed.'); } protected function authorizeConsultation(Request $request, Consultation $consultation): void { $this->authorizeOwner($request, $consultation); $consultation->loadMissing('visit'); abort_unless($consultation->visit->organization_id === $this->organization($request)->id, 404); $branchId = app(OrganizationResolver::class)->branchScope($this->member($request)); if ($branchId !== null && $consultation->visit->branch_id !== $branchId) { abort(404); } } /** * @return array */ protected function validatedConsultationData(Request $request, bool $canManage, bool $canVitals): array { $rules = []; if ($canManage) { $rules = array_merge($rules, [ 'symptoms' => ['nullable', 'string', 'max:10000'], 'clinical_notes' => ['nullable', 'string', 'max:20000'], 'practitioner_id' => ['nullable', 'integer', 'exists:care_practitioners,id'], 'diagnoses' => ['nullable', 'array'], 'diagnoses.*.code' => ['nullable', 'string', 'max:50'], 'diagnoses.*.description' => ['nullable', 'string', 'max:500'], 'diagnoses.*.is_primary' => ['nullable', 'boolean'], 'diagnoses.*.notes' => ['nullable', 'string', 'max:2000'], 'documents' => ['nullable', 'array'], 'documents.*' => ['file', 'max:10240', 'mimes:pdf,jpeg,png,jpg,webp'], ]); $canVitals = true; } if ($canVitals) { $rules['vitals'] = ['nullable', 'array']; $rules['vitals.bp_systolic'] = ['nullable', 'integer', 'min:50', 'max:300']; $rules['vitals.bp_diastolic'] = ['nullable', 'integer', 'min:30', 'max:200']; $rules['vitals.pulse'] = ['nullable', 'integer', 'min:20', 'max:250']; $rules['vitals.temperature'] = ['nullable', 'numeric', 'min:30', 'max:45']; $rules['vitals.weight_kg'] = ['nullable', 'numeric', 'min:0', 'max:500']; $rules['vitals.height_cm'] = ['nullable', 'numeric', 'min:0', 'max:300']; $rules['vitals.spo2'] = ['nullable', 'integer', 'min:50', 'max:100']; $rules['vitals.respiratory_rate'] = ['nullable', 'integer', 'min:5', 'max:80']; } return $request->validate($rules); } }