Ship commercial Dentistry suite with odontogram and treatment plans.
Deploy Ladill Care / deploy (push) Failing after 36s

Replace placeholder clinical forms with patient-level FDI charting, multi-visit plans, procedure-to-bill linking, imaging, reports, and demo seed data.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-18 16:33:34 +00:00
co-authored by Cursor
parent a00a8249ad
commit 0edd653187
37 changed files with 2906 additions and 35 deletions
@@ -155,9 +155,11 @@ class SpecialtyModuleController extends Controller
if ($openConsultation && $openConsultation->status !== \App\Models\Consultation::STATUS_COMPLETED) {
$clinical = app(SpecialtyClinicalRecordService::class);
$shellTabs = app(SpecialtyShellService::class)->workspaceTabs($module);
$preferredTab = collect(array_keys($shellTabs))
->first(fn (string $tab) => $clinical->recordTypeForTab($module, $tab) !== null)
?? 'clinical_notes';
$preferredTab = $module === 'dentistry'
? 'odontogram'
: (collect(array_keys($shellTabs))
->first(fn (string $tab) => $clinical->recordTypeForTab($module, $tab) !== null)
?? 'clinical_notes');
return redirect()
->route('care.specialty.workspace', [
@@ -196,9 +198,11 @@ class SpecialtyModuleController extends Controller
$visit = $visit->fresh() ?? $appointment->visit;
$clinical = app(SpecialtyClinicalRecordService::class);
$shellTabs = app(SpecialtyShellService::class)->workspaceTabs($module);
$preferredTab = collect(array_keys($shellTabs))
->first(fn (string $tab) => $clinical->recordTypeForTab($module, $tab) !== null)
?? 'clinical_notes';
$preferredTab = $module === 'dentistry'
? 'odontogram'
: (collect(array_keys($shellTabs))
->first(fn (string $tab) => $clinical->recordTypeForTab($module, $tab) !== null)
?? 'clinical_notes');
return redirect()
->route('care.specialty.workspace', [
@@ -503,6 +507,18 @@ class SpecialtyModuleController extends Controller
$clinicalFields = [];
$clinicalAlerts = [];
$visitDocuments = collect();
$dentalChart = null;
$dentalTeethMap = [];
$dentalPlan = null;
$dentalProcedures = collect();
$dentalImages = collect();
$dentalVisitNote = null;
$dentalCatalog = [];
$dentalRows = [];
$dentalConditions = [];
$dentalStatuses = [];
$dentalSurfaces = [];
$dentalModalities = [];
$activeTab = (string) $request->query('tab', array_key_first($shell->workspaceTabs($module)) ?: 'overview');
$clinical = app(SpecialtyClinicalRecordService::class);
@@ -553,6 +569,47 @@ class SpecialtyModuleController extends Controller
$clinicalFields = $clinical->fieldsFor($module, $recordType);
}
$clinicalAlerts = $clinical->alertsForVisit($workspaceVisit, $module);
if ($module === 'dentistry' && $workspaceVisit->patient) {
$chartService = app(\App\Services\Care\Dentistry\DentalChartService::class);
$planService = app(\App\Services\Care\Dentistry\DentalTreatmentPlanService::class);
$analytics = app(\App\Services\Care\Dentistry\DentalAnalyticsService::class);
$dentalChart = $chartService->chartForPatient($organization, $workspaceVisit->patient, $owner);
$dentalTeethMap = $chartService->teethMap($dentalChart);
$dentalPlan = $planService->activePlanForPatient($organization, $workspaceVisit->patient, $owner);
$dentalProcedures = \App\Models\DentalProcedure::owned($owner)
->where('visit_id', $workspaceVisit->id)
->orderByDesc('id')
->get();
$dentalImages = \App\Models\DentalImage::owned($owner)
->where(function ($q) use ($workspaceVisit) {
$q->where('visit_id', $workspaceVisit->id)
->orWhere(function ($q2) use ($workspaceVisit) {
$q2->where('patient_id', $workspaceVisit->patient_id)
->whereNull('visit_id');
});
})
->with('attachment')
->orderByDesc('id')
->limit(40)
->get();
$dentalVisitNote = \App\Models\DentalVisitNote::owned($owner)
->where('visit_id', $workspaceVisit->id)
->first();
$dentalCatalog = $shell->provisionedServices($organization, 'dentistry');
$dentalRows = \App\Services\Care\Dentistry\DentalCatalog::odontogramRows();
$dentalConditions = \App\Services\Care\Dentistry\DentalCatalog::conditions();
$dentalStatuses = \App\Services\Care\Dentistry\DentalCatalog::toothStatuses();
$dentalSurfaces = \App\Services\Care\Dentistry\DentalCatalog::surfaces();
$dentalModalities = \App\Services\Care\Dentistry\DentalCatalog::modalities();
$clinicalAlerts = array_merge(
$clinicalAlerts,
$analytics->alertsForPatient($organization, $workspaceVisit->patient, $owner),
);
}
if ($patientHeader !== null) {
$patientHeader['clinical_alerts'] = $clinicalAlerts;
}
@@ -593,6 +650,18 @@ class SpecialtyModuleController extends Controller
'clinicalFields' => $clinicalFields,
'clinicalAlerts' => $clinicalAlerts,
'visitDocuments' => $visitDocuments,
'dentalChart' => $dentalChart,
'dentalTeethMap' => $dentalTeethMap,
'dentalPlan' => $dentalPlan,
'dentalProcedures' => $dentalProcedures,
'dentalImages' => $dentalImages,
'dentalVisitNote' => $dentalVisitNote,
'dentalCatalog' => $dentalCatalog,
'dentalRows' => $dentalRows,
'dentalConditions' => $dentalConditions,
'dentalStatuses' => $dentalStatuses,
'dentalSurfaces' => $dentalSurfaces,
'dentalModalities' => $dentalModalities,
'queueStubs' => $modules->queueStubsFor($organization, $module),
'branchId' => $branchId,
'branchLabel' => $branchLabel,