Files
ladill-care/app/Http/Controllers/Care/SettingsController.php
T
isaaccladandCursor 015a4cc7fe
Deploy Ladill Care / deploy (push) Successful in 1m45s
Wire Care lists into Ladill Queue workflows instead of reception panels.
When Queue integration is on, role pages issue tickets into their own
department queues and drive Call next → Serve → Complete on the native
lists. Integration off leaves existing UI unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-17 16:27:48 +00:00

169 lines
7.6 KiB
PHP

<?php
namespace App\Http\Controllers\Care;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Models\Branch;
use App\Services\Care\AppointmentPatientNotifier;
use App\Services\Care\AuditLogger;
use App\Services\Care\CareFeatures;
use App\Services\Care\CarePermissions;
use App\Services\Care\CareQueueProvisioner;
use App\Services\Care\PlanService;
use App\Services\Billing\PlatformEmailClient;
use App\Services\Billing\PlatformSmsClient;
use App\Services\Messaging\MessagingCredentialsService;
use App\Services\Queue\QueueClient;
use App\Support\OrganizationBranding;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class SettingsController extends Controller
{
use ScopesToAccount;
public function edit(
Request $request,
MessagingCredentialsService $credentials,
PlatformEmailClient $platformEmail,
PlatformSmsClient $platformSms,
): View {
$this->authorizeAbility($request, 'settings.view');
$organization = $this->organization($request);
$member = $this->member($request);
$permissions = app(CarePermissions::class);
$canManage = $permissions->can($member, 'settings.manage');
$credential = $credentials->forOrganization($organization);
$branchCount = Branch::owned($this->ownerRef($request))
->where('organization_id', $organization->id)
->count();
$plans = app(PlanService::class);
// Suite platform keys (zero-config) OR optional product credentials.
$suiteEmailReady = $platformEmail->isConfigured();
$suiteSmsReady = $platformSms->isConfigured();
$careFeatures = app(CareFeatures::class);
return view('care.settings.edit', [
'organization' => $organization,
'canManage' => $canManage,
'branchCount' => $branchCount,
'canViewBranches' => $permissions->can($member, 'admin.branches.view'),
'canViewTeam' => $permissions->can($member, 'admin.members.view'),
'canViewDevices' => $permissions->can($member, 'devices.view'),
'hasBranchesFeature' => $plans->hasFeature($organization, 'branches'),
'hasClinicalDevicesFeature' => $plans->hasFeature($organization, 'clinical_devices'),
'canUseQueueIntegration' => $plans->canUseQueueIntegration($organization),
'canUseSpecialtyModules' => $plans->canUseSpecialtyModules($organization),
'assessmentsEngineEnabled' => $careFeatures->enabled($organization, CareFeatures::ASSESSMENTS_ENGINE),
'messagingSmsReady' => $suiteSmsReady || $credential->hasValidSms(),
'messagingEmailReady' => $suiteEmailReady || $credential->hasValidBird(),
'suiteMessagingReady' => $suiteEmailReady || $suiteSmsReady,
'messagingSettingsUrl' => function_exists('ladill_account_url')
? ladill_account_url('/account/settings/messaging')
: (string) config('smtp.messaging_settings_url', 'https://account.ladill.com/account/settings/messaging'),
'facilityTypes' => [
'clinic' => 'Clinic',
'hospital' => 'Hospital',
'diagnostic' => 'Diagnostic laboratory',
'specialist' => 'Specialist practice',
],
]);
}
public function update(Request $request, QueueClient $queue, CareQueueProvisioner $provisioner): RedirectResponse
{
$this->authorizeAbility($request, 'settings.manage');
$organization = $this->organization($request);
$owner = $this->ownerRef($request);
$plans = app(PlanService::class);
$validated = $request->validate([
'name' => ['required', 'string', 'max:255'],
'timezone' => ['required', 'timezone'],
'facility_type' => ['required', 'string', 'in:clinic,hospital,diagnostic,specialist'],
'logo' => ['nullable', 'image', 'mimes:jpeg,png,jpg,webp,svg', 'max:2048'],
'remove_logo' => ['nullable', 'boolean'],
'queue_integration_enabled' => ['nullable', 'boolean'],
'assessments_engine' => ['nullable', 'boolean'],
'notify_appointment_booked_sms' => ['nullable', 'boolean'],
'notify_appointment_booked_email' => ['nullable', 'boolean'],
'notify_video_scheduled_sms' => ['nullable', 'boolean'],
'notify_video_scheduled_email' => ['nullable', 'boolean'],
]);
$settings = $organization->settings ?? [];
$settings['onboarded'] = true;
$settings['facility_type'] = $validated['facility_type'];
$rollout = is_array($settings['rollout'] ?? null) ? $settings['rollout'] : [];
// Explicit save so opt-out is stored (engine defaults ON when unset).
$rollout[CareFeatures::ASSESSMENTS_ENGINE] = $request->boolean('assessments_engine');
$settings['rollout'] = $rollout;
if ($rollout[CareFeatures::ASSESSMENTS_ENGINE]) {
app(CareFeatures::class)->ensureAssessmentCatalog();
}
// Queue integration is Pro/Enterprise only — free plans cannot enable it.
$wantsQueue = $request->boolean('queue_integration_enabled');
if ($wantsQueue && ! $plans->canUseQueueIntegration($organization)) {
return redirect()
->route('care.pro.index')
->with('upsell', 'Ladill Queue integration is part of Care Pro. Upgrade to connect service queues and counters.');
}
if (! $plans->canUseQueueIntegration($organization)) {
$wantsQueue = false;
}
$settings['queue_integration_enabled'] = $wantsQueue;
$settings[AppointmentPatientNotifier::SETTING_BOOKED_SMS] = $request->boolean('notify_appointment_booked_sms');
$settings[AppointmentPatientNotifier::SETTING_BOOKED_EMAIL] = $request->boolean('notify_appointment_booked_email');
$settings[AppointmentPatientNotifier::SETTING_VIDEO_SMS] = $request->boolean('notify_video_scheduled_sms');
$settings[AppointmentPatientNotifier::SETTING_VIDEO_EMAIL] = $request->boolean('notify_video_scheduled_email');
if ($wantsQueue && $queue->configured()) {
$branch = Branch::owned($owner)->where('organization_id', $organization->id)->orderBy('name')->first();
try {
$queue->enable($owner, $organization->name, $branch?->name);
} catch (\Throwable) {
return back()->withInput()->with('error', 'Could not provision Ladill Queue for this account. Ensure Queue API keys are configured and Queue allows Care integration.');
}
}
$logoPath = $organization->logo_path;
if ($request->boolean('remove_logo')) {
OrganizationBranding::deleteStoredLogo($organization);
$logoPath = null;
}
if ($request->hasFile('logo')) {
$logoPath = OrganizationBranding::storeLogo($organization, $request->file('logo'));
}
$organization->update([
'name' => $validated['name'],
'timezone' => $validated['timezone'],
'logo_path' => $logoPath,
'settings' => $settings,
]);
if ($wantsQueue && $queue->configured()) {
try {
$provisioner->provisionOrganization($organization->fresh());
} catch (\Throwable) {
// Best-effort; role pages will lazy-ensure on next use.
}
}
AuditLogger::record($owner, 'organization.updated', $organization->id, $owner, \App\Models\Organization::class, $organization->id);
return back()->with('success', 'Settings saved.');
}
}