Assign every demo waiter to a doctor and sync Queue tickets.
Deploy Ladill Care / deploy (push) Successful in 1m54s
Deploy Ladill Care / deploy (push) Successful in 1m54s
Link DemoWorld doctor staff to practitioners, clear unresolved routing, distribute staff across branches, and restore scoped consultation/pharmacy ticket sync so demos are not left Unassigned. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -114,6 +114,7 @@ class DemoTenantSeeder
|
||||
$departments = $this->departmentsByBranch($branches, $ownerRef);
|
||||
}
|
||||
$practitioners = $this->seedPractitioners($organization, $branches, $departments, $ownerRef, $volumes);
|
||||
$this->linkStaffDoctorsToPractitioners($organization, $ownerRef, $plan, $branches, $practitioners);
|
||||
$patients = $this->seedPatients($organization, $branches, $ownerRef, $volumes);
|
||||
$appointmentCount = $this->seedAppointmentsAndClinical(
|
||||
$organization,
|
||||
@@ -124,6 +125,7 @@ class DemoTenantSeeder
|
||||
$ownerRef,
|
||||
$volumes,
|
||||
);
|
||||
$this->assignAllDemoWaiters($organization, $ownerRef, $branches, $practitioners);
|
||||
if (in_array($plan, ['pro', 'enterprise'], true)) {
|
||||
$appointmentCount += $this->seedSpecialtyDemoData(
|
||||
$organization->fresh(),
|
||||
@@ -173,10 +175,126 @@ class DemoTenantSeeder
|
||||
*/
|
||||
private function syncQueueTicketsForDemo(Organization $organization, array $branches): void
|
||||
{
|
||||
// Intentionally no-op during demo seed. Queue HTTP (branch × context) can
|
||||
// take many minutes on Enterprise volumes and hung production reseeds.
|
||||
// Specialty/care waiting lists still come from local appointments; Queue
|
||||
// tickets backfill lazily on first Ops / specialty page visit.
|
||||
if (! data_get($organization->settings, 'queue_integration_enabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$bridge = app(CareQueueBridge::class);
|
||||
if (! $bridge->isEnabled($organization)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scoped per branch/context (not full-org) so demos finish quickly while
|
||||
// still leaving waiters with real tickets instead of "Unassigned".
|
||||
$contexts = [
|
||||
CareQueueContexts::CONSULTATION,
|
||||
CareQueueContexts::PHARMACY,
|
||||
CareQueueContexts::LABORATORY,
|
||||
CareQueueContexts::BILLING,
|
||||
];
|
||||
|
||||
foreach ($branches as $branch) {
|
||||
foreach ($contexts as $context) {
|
||||
try {
|
||||
$bridge->syncMissingTickets($organization, $context, (int) $branch->id, 50);
|
||||
} catch (\Throwable) {
|
||||
// Continue — page load will retry for that context.
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
// Demo seed should not fail if Queue API is unreachable.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Point DemoWorld doctor staff at a real practitioner so Call next / rooms work.
|
||||
*
|
||||
* @param list<Branch> $branches
|
||||
* @param list<Practitioner> $practitioners
|
||||
*/
|
||||
private function linkStaffDoctorsToPractitioners(
|
||||
Organization $organization,
|
||||
string $ownerRef,
|
||||
string $plan,
|
||||
array $branches,
|
||||
array $practitioners,
|
||||
): void {
|
||||
$doctorEmail = null;
|
||||
$doctorName = null;
|
||||
foreach (DemoWorld::staff($plan) as $staff) {
|
||||
if (($staff['roles']['care'] ?? null) === 'doctor') {
|
||||
$doctorEmail = strtolower((string) $staff['email']);
|
||||
$doctorName = (string) $staff['name'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($doctorEmail === null || $practitioners === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$member = Member::query()
|
||||
->where('organization_id', $organization->id)
|
||||
->where('user_ref', $doctorEmail)
|
||||
->first();
|
||||
|
||||
$byBranch = [];
|
||||
foreach ($practitioners as $practitioner) {
|
||||
$byBranch[(int) $practitioner->branch_id] ??= $practitioner;
|
||||
}
|
||||
|
||||
foreach ($branches as $branch) {
|
||||
$practitioner = $byBranch[(int) $branch->id] ?? null;
|
||||
if (! $practitioner) {
|
||||
continue;
|
||||
}
|
||||
$practitioner->forceFill([
|
||||
'user_ref' => $doctorEmail,
|
||||
'member_id' => $member?->id,
|
||||
'name' => $doctorName !== '' ? $doctorName : $practitioner->name,
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Every waiting / checked-in demo appointment gets a doctor and a clean routing
|
||||
* state so Queue sync can issue tickets (no amber Unassigned leftovers).
|
||||
*
|
||||
* @param list<Branch> $branches
|
||||
* @param list<Practitioner> $practitioners
|
||||
*/
|
||||
private function assignAllDemoWaiters(
|
||||
Organization $organization,
|
||||
string $ownerRef,
|
||||
array $branches,
|
||||
array $practitioners,
|
||||
): void {
|
||||
if ($practitioners === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$byBranch = [];
|
||||
foreach ($practitioners as $practitioner) {
|
||||
$byBranch[(int) $practitioner->branch_id][] = $practitioner;
|
||||
}
|
||||
|
||||
$waiters = Appointment::withTrashed()
|
||||
->owned($ownerRef)
|
||||
->where('organization_id', $organization->id)
|
||||
->whereIn('status', [Appointment::STATUS_WAITING, Appointment::STATUS_CHECKED_IN])
|
||||
->get();
|
||||
|
||||
foreach ($waiters as $index => $appointment) {
|
||||
$branchPracs = $byBranch[(int) $appointment->branch_id] ?? $practitioners;
|
||||
$practitioner = $branchPracs[$index % max(1, count($branchPracs))] ?? $practitioners[0];
|
||||
|
||||
$appointment->forceFill([
|
||||
'practitioner_id' => $practitioner->id,
|
||||
'queue_routing_status' => null,
|
||||
'deleted_at' => null,
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -473,18 +591,25 @@ class DemoTenantSeeder
|
||||
|
||||
/**
|
||||
* Local Member rows for DemoWorld staff (user_ref = email until SSO remaps to public_id).
|
||||
* Multi-branch demos spread staff across branches so each site has a role roster.
|
||||
*
|
||||
* @param list<Branch> $branches
|
||||
*/
|
||||
private function seedStaffMembers(Organization $organization, string $ownerRef, string $plan, array $branches): void
|
||||
{
|
||||
$hq = $branches[0] ?? null;
|
||||
foreach (DemoWorld::staff($plan) as $staff) {
|
||||
$staffList = DemoWorld::staff($plan);
|
||||
foreach ($staffList as $index => $staff) {
|
||||
$role = $staff['roles']['care'] ?? null;
|
||||
if (! is_string($role) || $role === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$branch = $hq;
|
||||
if ($role !== 'hospital_admin' && $branches !== []) {
|
||||
$branch = $branches[$index % count($branches)];
|
||||
}
|
||||
|
||||
Member::query()->updateOrCreate(
|
||||
[
|
||||
'organization_id' => $organization->id,
|
||||
@@ -493,7 +618,7 @@ class DemoTenantSeeder
|
||||
[
|
||||
'owner_ref' => $ownerRef,
|
||||
'role' => $role,
|
||||
'branch_id' => in_array($role, ['hospital_admin'], true) ? null : $hq?->id,
|
||||
'branch_id' => $role === 'hospital_admin' ? null : $branch?->id,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user