Deploy Ladill Care / deploy (push) Successful in 26s
Keeps Fertility as a separate specialty, adds OB/GYN and fertility staff roles, and migrates live org settings from maternity → womens_health. Co-authored-by: Cursor <cursoragent@cursor.com>
178 lines
6.8 KiB
PHP
178 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Care;
|
|
|
|
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Services\Care\CarePermissions;
|
|
use App\Services\Care\CarePricingService;
|
|
use App\Services\Care\PlanService;
|
|
use App\Services\Care\SpecialtyModuleService;
|
|
use App\Services\Care\SpecialtyShellService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\View\View;
|
|
|
|
class SettingsModulesController extends Controller
|
|
{
|
|
use ScopesToAccount;
|
|
|
|
public function edit(Request $request, SpecialtyModuleService $modules, PlanService $plans): View
|
|
{
|
|
$this->authorizeAbility($request, 'settings.view');
|
|
$organization = $this->organization($request);
|
|
$member = $this->member($request);
|
|
$canManage = app(CarePermissions::class)->can($member, 'settings.manage');
|
|
|
|
if ($modules->canManage($organization)) {
|
|
$modules->ensureDefaultModulesProvisioned($organization, $this->ownerRef($request));
|
|
$organization->refresh();
|
|
}
|
|
|
|
return view('care.settings.modules', [
|
|
'organization' => $organization,
|
|
'canManage' => $canManage,
|
|
'canUseSpecialtyModules' => $modules->canManage($organization),
|
|
'catalog' => $modules->catalog(),
|
|
'enabled' => collect($modules->enabledKeys($organization))->flip()->all(),
|
|
'planKey' => $plans->planKey($organization),
|
|
]);
|
|
}
|
|
|
|
public function show(
|
|
Request $request,
|
|
string $module,
|
|
SpecialtyModuleService $modules,
|
|
SpecialtyShellService $shell,
|
|
CarePricingService $pricing,
|
|
): View {
|
|
$this->authorizeAbility($request, 'settings.view');
|
|
$module = $modules->normalizeKey($module);
|
|
$definition = $modules->definition($module);
|
|
abort_unless($definition, 404);
|
|
|
|
$organization = $this->organization($request);
|
|
$member = $this->member($request);
|
|
$canManage = app(CarePermissions::class)->can($member, 'settings.manage');
|
|
$canUse = $modules->canManage($organization);
|
|
|
|
if ($canUse && $modules->isEnabled($organization, $module)) {
|
|
$shell->seedServices($organization, $module);
|
|
$organization->refresh();
|
|
}
|
|
|
|
$services = $canUse
|
|
? $shell->provisionedServices($organization, $module)
|
|
: $shell->catalogServices($module);
|
|
|
|
return view('care.settings.module-show', [
|
|
'organization' => $organization,
|
|
'moduleKey' => $module,
|
|
'definition' => $definition,
|
|
'services' => $services,
|
|
'serviceLines' => $modules->serviceLines($module),
|
|
'enabledServiceLines' => $modules->enabledServiceLines($organization, $module),
|
|
'enabled' => $modules->isEnabled($organization, $module),
|
|
'canManage' => $canManage && $canUse,
|
|
'canUseSpecialtyModules' => $canUse,
|
|
'canOpenWorkspace' => $modules->memberCanAccess($organization, $member, $module),
|
|
'currency' => strtoupper((string) config('care.billing.currency', 'GHS')),
|
|
]);
|
|
}
|
|
|
|
public function updateServiceLines(
|
|
Request $request,
|
|
string $module,
|
|
SpecialtyModuleService $modules,
|
|
): RedirectResponse {
|
|
$this->authorizeAbility($request, 'settings.manage');
|
|
$organization = $this->organization($request);
|
|
abort_unless($modules->definition($module), 404);
|
|
abort_unless($modules->canManage($organization), 403);
|
|
abort_unless($modules->serviceLines($module) !== [], 404);
|
|
|
|
$lines = $modules->serviceLines($module);
|
|
$rules = ['lines' => ['required', 'array']];
|
|
foreach (array_keys($lines) as $key) {
|
|
$rules["lines.{$key}"] = ['nullable', 'boolean'];
|
|
}
|
|
$validated = $request->validate($rules);
|
|
|
|
$desired = [];
|
|
foreach (array_keys($lines) as $key) {
|
|
$desired[$key] = (bool) ($validated['lines'][$key] ?? false);
|
|
}
|
|
|
|
$modules->syncServiceLines($organization, $module, $desired);
|
|
|
|
return redirect()
|
|
->route('care.settings.modules.show', $module)
|
|
->with('success', 'Service lines saved.');
|
|
}
|
|
|
|
public function updateServices(
|
|
Request $request,
|
|
string $module,
|
|
SpecialtyModuleService $modules,
|
|
SpecialtyShellService $shell,
|
|
CarePricingService $pricing,
|
|
): RedirectResponse {
|
|
$this->authorizeAbility($request, 'settings.manage');
|
|
$organization = $this->organization($request);
|
|
abort_unless($modules->definition($module), 404);
|
|
abort_unless($modules->canManage($organization), 403);
|
|
|
|
$validated = $request->validate([
|
|
'services' => ['required', 'array'],
|
|
'services.*.code' => ['required', 'string', 'max:64'],
|
|
'services.*.amount' => ['required', 'numeric', 'min:0', 'max:999999'],
|
|
'services.*.label' => ['nullable', 'string', 'max:255'],
|
|
]);
|
|
|
|
$shell->seedServices($organization, $module);
|
|
$pricing->updateSpecialtyServices($organization->fresh(), $module, $validated['services'], $shell);
|
|
|
|
return redirect()
|
|
->route('care.settings.modules.show', $module)
|
|
->with('success', 'Service prices saved.');
|
|
}
|
|
|
|
public function update(Request $request, SpecialtyModuleService $modules): RedirectResponse
|
|
{
|
|
$this->authorizeAbility($request, 'settings.manage');
|
|
$organization = $this->organization($request);
|
|
|
|
if (! $modules->canManage($organization)) {
|
|
return redirect()
|
|
->route('care.pro.index')
|
|
->with('upsell', 'Specialty modules are part of Care Pro. Upgrade to activate dentistry, eye care, and other specialty practice surfaces.');
|
|
}
|
|
|
|
$keys = array_keys($modules->catalog());
|
|
$desired = [];
|
|
foreach ($keys as $key) {
|
|
$desired[$key] = $request->boolean("modules.{$key}");
|
|
if ($modules->isDefaultOnPaidPlans($key)) {
|
|
$desired[$key] = true;
|
|
}
|
|
}
|
|
|
|
$modules->ensureDefaultModulesProvisioned($organization, $this->ownerRef($request));
|
|
$result = $modules->sync($organization->fresh(), $this->ownerRef($request), $desired);
|
|
|
|
if ($result['errors'] !== []) {
|
|
return back()->with('error', 'Some modules could not be updated: '.implode(' ', $result['errors']));
|
|
}
|
|
|
|
$parts = [];
|
|
if ($result['activated'] !== []) {
|
|
$parts[] = 'Activated '.count($result['activated']).' module(s)';
|
|
}
|
|
if ($result['deactivated'] !== []) {
|
|
$parts[] = 'Deactivated '.count($result['deactivated']).' module(s)';
|
|
}
|
|
|
|
return back()->with('success', $parts !== [] ? implode('. ', $parts).'.' : 'Modules saved.');
|
|
}
|
|
}
|