authorizeAbility($request, 'patients.view'); $organization = $this->organization($request); $branchScope = app(OrganizationResolver::class)->branchScope($this->member($request)); $patients = $this->patients->search( $this->ownerRef($request), $organization->id, $request->only(['q', 'patient_number', 'phone', 'national_id', 'date_of_birth', 'per_page']), $branchScope, ); return response()->json($patients); } public function store(Request $request): JsonResponse { $this->authorizeAbility($request, 'patients.manage'); $organization = $this->organization($request); $patient = $this->patients->create( $organization, $this->ownerRef($request), $this->validatedPatientData($request), $this->ownerRef($request), ); return response()->json($patient, 201); } public function show(Request $request, Patient $patient): JsonResponse { $this->authorizeAbility($request, 'patients.view'); $this->authorizePatient($request, $patient); return response()->json($this->patients->dashboard($patient)); } public function update(Request $request, Patient $patient): JsonResponse { $this->authorizeAbility($request, 'patients.manage'); $this->authorizePatient($request, $patient); $updated = $this->patients->update( $patient, $this->ownerRef($request), $this->validatedPatientData($request), $this->ownerRef($request), ); return response()->json($updated); } public function destroy(Request $request, Patient $patient): JsonResponse { $this->authorizeAbility($request, 'patients.manage'); $this->authorizePatient($request, $patient); $this->patients->delete($patient, $this->ownerRef($request), $this->ownerRef($request)); return response()->json(['message' => 'Patient archived.']); } protected function authorizePatient(Request $request, Patient $patient): void { $this->authorizeOwner($request, $patient); 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) { 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); } /** * @return array */ protected function validatedPatientData(Request $request): array { return $request->validate([ 'branch_id' => ['nullable', 'integer', 'exists:care_branches,id'], 'first_name' => ['required', 'string', 'max:100'], 'last_name' => ['required', 'string', 'max:100'], 'other_names' => ['nullable', 'string', 'max:100'], 'gender' => ['nullable', 'string', 'in:'.implode(',', array_keys(config('care.genders')))], 'date_of_birth' => ['nullable', 'date', 'before:today'], 'phone' => ['nullable', 'string', 'max:30'], 'email' => ['nullable', 'email', 'max:255'], 'national_id' => ['nullable', 'string', 'max:50'], 'address' => ['nullable', 'string', 'max:500'], 'city' => ['nullable', 'string', 'max:100'], 'region' => ['nullable', 'string', 'max:100'], 'notes' => ['nullable', 'string', 'max:5000'], 'allergies' => ['nullable', 'array'], 'conditions' => ['nullable', 'array'], 'family_history' => ['nullable', 'array'], 'emergency_contacts' => ['nullable', 'array'], 'insurance' => ['nullable', 'array'], ]); } }