Files
ladill-care/app/Http/Controllers/Care/OutcomeController.php
T
isaacclad f6780b9958
Deploy Ladill Care / deploy (push) Successful in 54s
fix(assessments): enable engine by default and wire into live UI
The assessment engine was built but opt-in and hidden: flag defaulted
off, no sidebar entry, and no settings toggle. Default assessments_engine
on, auto-seed catalog when empty, add Settings toggle and Assessments
nav, and surface guidance from the patients list.
2026-07-16 23:05:48 +00:00

111 lines
4.0 KiB
PHP

<?php
namespace App\Http\Controllers\Care;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Http\Controllers\Controller;
use App\Models\Patient;
use App\Services\Care\AssessmentService;
use App\Services\Care\CareFeatures;
use App\Services\Care\CarePermissions;
use App\Services\Care\OrganizationResolver;
use App\Services\Care\OutcomeTrendService;
use App\Services\Care\PlanService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class OutcomeController extends Controller
{
use ScopesToAccount;
public function __construct(
protected OutcomeTrendService $trends,
protected AssessmentService $assessments,
protected CareFeatures $features,
protected CarePermissions $permissions,
protected PlanService $plans,
) {}
/**
* Per-patient outcome history + instrument score trends (free).
*/
public function index(Request $request, Patient $patient): View
{
$this->assertEngineEnabled($request);
$this->authorizeAbility($request, 'assessments.view');
$this->authorizePatient($request, $patient);
$branchScope = app(OrganizationResolver::class)->branchScope($this->member($request));
$ownerRef = $this->ownerRef($request);
$outcomeSeries = $this->trends->outcomeSeries($patient, $ownerRef, $branchScope);
$scores = $this->trends->instrumentScores($patient, $ownerRef, $branchScope);
$vitals = $this->trends->recentVitals($patient, $ownerRef);
$canCapture = $this->permissions->can($this->member($request), 'assessments.capture')
|| $this->permissions->can($this->member($request), 'assessments.manage');
// Org-level multi-patient analytics is Enterprise (KD-18); surface a notice only.
$canOrgAnalytics = $this->plans->isEnterprise($this->organization($request));
return view('care.outcomes.index', [
'patient' => $patient,
'outcomeSeries' => $outcomeSeries,
'scores' => $scores,
'vitals' => $vitals,
'canCapture' => $canCapture,
'canOrgAnalytics' => $canOrgAnalytics,
'qolSeries' => $this->trends->numericOutcomeSeries($patient, $ownerRef, 'quality_of_life', $branchScope),
'painSeries' => $this->trends->numericOutcomeSeries($patient, $ownerRef, 'pain_score', $branchScope),
'statuses' => config('care.assessment_statuses'),
]);
}
/**
* Start a new outcome_core draft for the patient.
*/
public function store(Request $request, Patient $patient): RedirectResponse
{
$this->assertEngineEnabled($request);
abort_unless(
$this->permissions->can($this->member($request), 'assessments.capture')
|| $this->permissions->can($this->member($request), 'assessments.manage'),
403,
);
$this->authorizePatient($request, $patient);
$assessment = $this->assessments->start(
$patient,
OutcomeTrendService::OUTCOME_TEMPLATE_CODE,
$this->ownerRef($request),
$this->member($request),
['actor' => $this->ownerRef($request)],
);
return redirect()
->route('care.assessments.show', $assessment)
->with('success', 'Outcome assessment started.');
}
protected function assertEngineEnabled(Request $request): void
{
abort_unless(
$this->features->enabled($this->organization($request), CareFeatures::ASSESSMENTS_ENGINE),
404,
);
$this->features->ensureAssessmentCatalog();
}
protected function authorizePatient(Request $request, Patient $patient): void
{
$this->authorizeOwner($request, $patient);
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);
}
}
}