Restrict specialty modules to doctors assigned to that specialty.
Deploy Ladill Care / deploy (push) Successful in 1m10s
Deploy Ladill Care / deploy (push) Successful in 1m10s
Nav and pages require a linked practitioner desk in the module department; demo seeds specialty doctors and stops overwriting their assigned waiters. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -132,6 +132,7 @@ class DemoTenantSeeder
|
||||
$practitioners,
|
||||
$patients,
|
||||
$ownerRef,
|
||||
$plan,
|
||||
);
|
||||
}
|
||||
$this->assignAllDemoWaiters($organization, $ownerRef, $branches, $practitioners);
|
||||
@@ -286,6 +287,9 @@ class DemoTenantSeeder
|
||||
->owned($ownerRef)
|
||||
->where('organization_id', $organization->id)
|
||||
->whereIn('status', [Appointment::STATUS_WAITING, Appointment::STATUS_CHECKED_IN])
|
||||
->where(function ($q) {
|
||||
$q->whereNull('practitioner_id')->orWhere('practitioner_id', 0);
|
||||
})
|
||||
->get();
|
||||
|
||||
foreach ($waiters as $index => $appointment) {
|
||||
@@ -772,6 +776,7 @@ class DemoTenantSeeder
|
||||
array $practitioners,
|
||||
array $patients,
|
||||
string $ownerRef,
|
||||
string $plan = 'pro',
|
||||
): int {
|
||||
if ($branches === [] || $patients === [] || $practitioners === []) {
|
||||
return 0;
|
||||
@@ -789,6 +794,9 @@ class DemoTenantSeeder
|
||||
$catalog = config('care.specialty_modules', []);
|
||||
/** @var array<int, int> $nextPositionByBranch */
|
||||
$nextPositionByBranch = [];
|
||||
/** @var array<string, Member|null> $moduleMembers */
|
||||
$moduleMembers = [];
|
||||
|
||||
foreach ($catalog as $key => $definition) {
|
||||
$type = (string) ($definition['department_type'] ?? '');
|
||||
if ($type === '') {
|
||||
@@ -796,6 +804,11 @@ class DemoTenantSeeder
|
||||
}
|
||||
|
||||
$moduleReasons = $reasons[$key] ?? ['Specialty visit'];
|
||||
$staffEmail = sprintf('demo-%s-%s@ladill.com', $plan, $key);
|
||||
$moduleMembers[$key] = Member::query()
|
||||
->where('organization_id', $organization->id)
|
||||
->where('user_ref', $staffEmail)
|
||||
->first();
|
||||
|
||||
foreach ($branches as $branchIndex => $branch) {
|
||||
$department = Department::owned($ownerRef)
|
||||
@@ -807,17 +820,22 @@ class DemoTenantSeeder
|
||||
continue;
|
||||
}
|
||||
|
||||
$member = $moduleMembers[$key];
|
||||
$staff = $member ? \App\Support\DemoWorld::staffByEmail($staffEmail) : null;
|
||||
$stableRef = sprintf('demo-specialty-%s-%s', $key, $branch->id);
|
||||
$practitioner = Practitioner::withTrashed()->updateOrCreate(
|
||||
[
|
||||
'organization_id' => $organization->id,
|
||||
'user_ref' => sprintf('demo-specialty-%s-%s', $key, $branch->id),
|
||||
'user_ref' => $stableRef,
|
||||
],
|
||||
[
|
||||
'owner_ref' => $ownerRef,
|
||||
'branch_id' => $branch->id,
|
||||
'department_id' => $department->id,
|
||||
'member_id' => null,
|
||||
'name' => ($definition['label'] ?? ucfirst($key)).' Clinic',
|
||||
'member_id' => $member?->id,
|
||||
'name' => is_array($staff)
|
||||
? (string) $staff['name']
|
||||
: (($definition['label'] ?? ucfirst($key)).' Clinic'),
|
||||
'specialty' => (string) ($definition['label'] ?? $key),
|
||||
'room' => ($definition['label'] ?? 'Specialty').' Bay',
|
||||
'is_active' => true,
|
||||
|
||||
@@ -4,7 +4,9 @@ namespace App\Services\Care;
|
||||
|
||||
use App\Models\Branch;
|
||||
use App\Models\Department;
|
||||
use App\Models\Member;
|
||||
use App\Models\Organization;
|
||||
use App\Models\Practitioner;
|
||||
use App\Services\Queue\QueueClient;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -79,6 +81,86 @@ class SpecialtyModuleService
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enabled modules the member may open (role allowlist + doctor specialty assignment).
|
||||
*
|
||||
* @return list<array{key: string, definition: array<string, mixed>}>
|
||||
*/
|
||||
public function enabledModulesForMember(Organization $organization, ?Member $member): array
|
||||
{
|
||||
return array_values(array_filter(
|
||||
$this->enabledModules($organization),
|
||||
fn (array $item) => $this->memberCanAccess($organization, $member, $item['key']),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the member may see/serve this specialty module.
|
||||
* Doctors must be linked to a practitioner desk in that specialty department.
|
||||
* Admins/receptionists keep org-wide visibility for operations.
|
||||
*/
|
||||
public function memberCanAccess(Organization $organization, ?Member $member, string $key): bool
|
||||
{
|
||||
if (! $this->isEnabled($organization, $key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$definition = $this->definition($key);
|
||||
if (! $definition) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$roles = $definition['roles'] ?? [];
|
||||
if (is_array($roles) && $roles !== [] && $member && ! in_array($member->role, $roles, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($member && $member->role === 'doctor') {
|
||||
return $this->doctorAssignedToModule($organization, $member, $key);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function doctorAssignedToModule(Organization $organization, Member $member, string $key): bool
|
||||
{
|
||||
$definition = $this->definition($key);
|
||||
if (! $definition) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$departmentType = (string) ($definition['department_type'] ?? '');
|
||||
$provisionedIds = data_get(
|
||||
$organization->settings,
|
||||
"specialty_module_provisioning.{$key}.department_ids",
|
||||
[],
|
||||
);
|
||||
$provisionedIds = is_array($provisionedIds)
|
||||
? array_map('intval', $provisionedIds)
|
||||
: [];
|
||||
|
||||
$practitioners = Practitioner::owned((string) $organization->owner_ref)
|
||||
->where('organization_id', $organization->id)
|
||||
->where('is_active', true)
|
||||
->where(function ($query) use ($member) {
|
||||
$query->where('member_id', $member->id)
|
||||
->orWhere('user_ref', $member->user_ref);
|
||||
})
|
||||
->with('department')
|
||||
->get();
|
||||
|
||||
foreach ($practitioners as $practitioner) {
|
||||
if ($provisionedIds !== [] && in_array((int) $practitioner->department_id, $provisionedIds, true)) {
|
||||
return true;
|
||||
}
|
||||
if ($departmentType !== '' && $practitioner->department?->type === $departmentType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function canManage(Organization $organization): bool
|
||||
{
|
||||
return $this->plans->hasFeature($organization, 'specialty_modules');
|
||||
|
||||
Reference in New Issue
Block a user