Healthcare management app: patients, appointments, consultations, lab, pharmacy inventory, billing, and reports at care.ladill.com. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Care;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
|
||||
use App\Models\Consultation;
|
||||
use App\Models\InvestigationType;
|
||||
use App\Models\Practitioner;
|
||||
use App\Services\Care\ConsultationService;
|
||||
use App\Services\Care\OrganizationResolver;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ConsultationController extends Controller
|
||||
{
|
||||
use ScopesToAccount;
|
||||
|
||||
public function __construct(
|
||||
protected ConsultationService $consultations,
|
||||
) {}
|
||||
|
||||
public function show(Request $request, Consultation $consultation): View
|
||||
{
|
||||
$this->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<string, mixed>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user