Issue Queue tickets for every waiting appointment when integration is on.
Deploy Ladill Care / deploy (push) Successful in 51s
Deploy Ladill Care / deploy (push) Successful in 51s
Patient queue syncs consultation and specialty waiters; specialty contexts now provision desks so check-in/onboarding no longer leaves half the list on local positions only. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -198,9 +198,21 @@ class CareQueueProvisioner
|
||||
$owner = (string) $organization->owner_ref;
|
||||
$priorByKey = collect($stub['points'] ?? [])->keyBy(fn ($p) => (string) ($p['external_key'] ?? ''));
|
||||
|
||||
$points = match ($context) {
|
||||
CareQueueContexts::CONSULTATION => $this->practitionerPoints($organization, $branch, $priorByKey),
|
||||
CareQueueContexts::TRIAGE => $this->memberRolePoints(
|
||||
$points = match (true) {
|
||||
$context === CareQueueContexts::CONSULTATION => $this->practitionerPoints(
|
||||
$organization,
|
||||
$branch,
|
||||
CareQueueContexts::CONSULTATION,
|
||||
$priorByKey,
|
||||
),
|
||||
CareQueueContexts::isSpecialty($context) => $this->practitionerPoints(
|
||||
$organization,
|
||||
$branch,
|
||||
$context,
|
||||
$priorByKey,
|
||||
data_get($organization->settings, "specialty_module_provisioning.{$context}.department_ids", []),
|
||||
),
|
||||
$context === CareQueueContexts::TRIAGE => $this->memberRolePoints(
|
||||
$organization,
|
||||
$branch,
|
||||
['nurse'],
|
||||
@@ -208,7 +220,7 @@ class CareQueueProvisioner
|
||||
'Nurse station',
|
||||
$priorByKey,
|
||||
),
|
||||
CareQueueContexts::PHARMACY => $this->memberRolePoints(
|
||||
$context === CareQueueContexts::PHARMACY => $this->memberRolePoints(
|
||||
$organization,
|
||||
$branch,
|
||||
['pharmacist'],
|
||||
@@ -216,7 +228,7 @@ class CareQueueProvisioner
|
||||
'Pharmacy counter',
|
||||
$priorByKey,
|
||||
),
|
||||
CareQueueContexts::LABORATORY, CareQueueContexts::IMAGING => $this->memberRolePoints(
|
||||
in_array($context, [CareQueueContexts::LABORATORY, CareQueueContexts::IMAGING], true) => $this->memberRolePoints(
|
||||
$organization,
|
||||
$branch,
|
||||
['lab_technician'],
|
||||
@@ -224,7 +236,7 @@ class CareQueueProvisioner
|
||||
$context === CareQueueContexts::IMAGING ? 'Imaging room' : 'Lab desk',
|
||||
$priorByKey,
|
||||
),
|
||||
CareQueueContexts::BILLING => $this->memberRolePoints(
|
||||
$context === CareQueueContexts::BILLING => $this->memberRolePoints(
|
||||
$organization,
|
||||
$branch,
|
||||
['cashier'],
|
||||
@@ -232,7 +244,7 @@ class CareQueueProvisioner
|
||||
'Cashier desk',
|
||||
$priorByKey,
|
||||
),
|
||||
CareQueueContexts::RECEPTION => $this->memberRolePoints(
|
||||
$context === CareQueueContexts::RECEPTION => $this->memberRolePoints(
|
||||
$organization,
|
||||
$branch,
|
||||
['receptionist'],
|
||||
@@ -264,23 +276,37 @@ class CareQueueProvisioner
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<int|string>|null $departmentIds
|
||||
* @param \Illuminate\Support\Collection<string, array<string, mixed>> $priorByKey
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
protected function practitionerPoints(Organization $organization, Branch $branch, $priorByKey): array
|
||||
{
|
||||
protected function practitionerPoints(
|
||||
Organization $organization,
|
||||
Branch $branch,
|
||||
string $context,
|
||||
$priorByKey,
|
||||
?array $departmentIds = null,
|
||||
): array {
|
||||
$practitioners = Practitioner::owned($organization->owner_ref)
|
||||
->where('organization_id', $organization->id)
|
||||
->where('branch_id', $branch->id)
|
||||
->where('is_active', true)
|
||||
->when(
|
||||
is_array($departmentIds) && $departmentIds !== [],
|
||||
fn ($q) => $q->whereIn('department_id', array_map('intval', $departmentIds)),
|
||||
)
|
||||
->orderBy('name')
|
||||
->get();
|
||||
|
||||
$points = [];
|
||||
$roomIndex = 1;
|
||||
$roomPrefix = CareQueueContexts::isSpecialty($context)
|
||||
? (string) (config("care.specialty_modules.{$context}.label") ?? 'Room')
|
||||
: 'Consultation Room';
|
||||
|
||||
foreach ($practitioners as $practitioner) {
|
||||
$key = CareQueueContexts::pointExternalKey(
|
||||
CareQueueContexts::CONSULTATION,
|
||||
$context,
|
||||
$branch->id,
|
||||
'practitioner',
|
||||
$practitioner->id,
|
||||
@@ -288,7 +314,7 @@ class CareQueueProvisioner
|
||||
$prior = $priorByKey->get($key, []);
|
||||
$room = trim((string) ($practitioner->room ?? ''));
|
||||
if ($room === '') {
|
||||
$room = 'Consultation Room '.$roomIndex;
|
||||
$room = $roomPrefix.' '.$roomIndex;
|
||||
}
|
||||
$roomIndex++;
|
||||
|
||||
@@ -407,13 +433,17 @@ class CareQueueProvisioner
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a service point for a practitioner (consultation) or member staff_ref.
|
||||
* Resolve a service point for a practitioner on a queue context.
|
||||
*
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function pointForPractitioner(Organization $organization, int $branchId, int $practitionerId): ?array
|
||||
{
|
||||
$resources = $this->resourcesFor($organization, CareQueueContexts::CONSULTATION, $branchId);
|
||||
public function pointForPractitioner(
|
||||
Organization $organization,
|
||||
int $branchId,
|
||||
int $practitionerId,
|
||||
string $context = CareQueueContexts::CONSULTATION,
|
||||
): ?array {
|
||||
$resources = $this->resourcesFor($organization, $context, $branchId);
|
||||
if (! $resources) {
|
||||
return null;
|
||||
}
|
||||
@@ -495,7 +525,11 @@ class CareQueueProvisioner
|
||||
if ($existing && ! empty($existing['queue_uuid']) && (
|
||||
! empty($existing['points']) || ! empty($existing['counter_uuid'])
|
||||
) && $modeMatches) {
|
||||
return $existing;
|
||||
// Specialty module stubs often only store a legacy counter — still provision
|
||||
// practitioner points so check-in / sync can assign real desks.
|
||||
if (! CareQueueContexts::isSpecialty($context) || ! empty($existing['points'])) {
|
||||
return $existing;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $this->shouldProvision($organization)) {
|
||||
@@ -503,7 +537,8 @@ class CareQueueProvisioner
|
||||
}
|
||||
|
||||
if (CareQueueContexts::isSpecialty($context)) {
|
||||
return $existing;
|
||||
return $this->provisionSpecialtyContextBranch($organization->fresh(), $context, $branchId)
|
||||
?? $existing;
|
||||
}
|
||||
|
||||
if (! CareQueueContexts::isDepartment($context)) {
|
||||
@@ -515,6 +550,69 @@ class CareQueueProvisioner
|
||||
return $this->resourcesFor($organization->fresh(), $context, $branchId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provision a single specialty queue for one branch (idempotent).
|
||||
*
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function provisionSpecialtyContextBranch(Organization $organization, string $context, int $branchId): ?array
|
||||
{
|
||||
if (! CareQueueContexts::isSpecialty($context) || ! $this->shouldProvision($organization)) {
|
||||
return $this->resourcesFor($organization, $context, $branchId);
|
||||
}
|
||||
|
||||
$definition = config("care.specialty_modules.{$context}");
|
||||
if (! is_array($definition)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$branch = Branch::owned((string) $organization->owner_ref)
|
||||
->where('organization_id', $organization->id)
|
||||
->whereKey($branchId)
|
||||
->first();
|
||||
if (! $branch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$meta = [
|
||||
'name' => (string) ($definition['queue_name'] ?? $definition['label'] ?? $context),
|
||||
'prefix' => (string) ($definition['queue_prefix'] ?? strtoupper(substr($context, 0, 3))),
|
||||
'routing_mode' => 'assigned_only',
|
||||
'type' => 'consultation',
|
||||
];
|
||||
|
||||
$provisioning = (array) data_get($organization->settings, 'specialty_module_provisioning', []);
|
||||
$record = is_array($provisioning[$context] ?? null) ? $provisioning[$context] : [];
|
||||
$queues = is_array($record['queues'] ?? null) ? $record['queues'] : [];
|
||||
$byBranch = collect($queues)->keyBy(fn ($q) => (string) ($q['branch_id'] ?? ''));
|
||||
$prior = $byBranch->get((string) $branch->id, []);
|
||||
if (! is_array($prior)) {
|
||||
$prior = [];
|
||||
}
|
||||
$prior['module'] = $context;
|
||||
|
||||
$stub = $this->provisionBranchDepartment(
|
||||
$organization,
|
||||
(string) $organization->owner_ref,
|
||||
$context,
|
||||
$meta,
|
||||
$branch,
|
||||
$prior,
|
||||
);
|
||||
$byBranch->put((string) $branch->id, $stub);
|
||||
|
||||
$provisioning[$context] = array_merge($record, [
|
||||
'active' => true,
|
||||
'queues' => $byBranch->values()->all(),
|
||||
]);
|
||||
|
||||
$settings = $organization->settings ?? [];
|
||||
$settings['specialty_module_provisioning'] = $provisioning;
|
||||
$organization->update(['settings' => $settings]);
|
||||
|
||||
return $stub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provision a single department queue for one branch (idempotent).
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user