Seeking Community Input: How should the Service queues page resolve queue locations from the login location?

Background

The Service queues page (/spa/home/service-queues) shows a “Patients Currently In Queue” list and metric cards (Checked-in patients, Waiting for, Average wait time). The list and the Service filter are meant to be scoped to the user’s active queue location, but in practice the page has been returning queue entries regardless of where the user logged in — patients added at one location surface for every other login and switching the session location doesn’t change what you see.

The mechanical fix is straightforward, but resolving which queue locations are relevant to a given login location is a product decision, and I’d like implementer input before we lock in the behavior.

Related:

  1. O3-5711 on Jira
  2. PR #2550 on GitHub

Current behavior (on dev3)

dev3 has one “Queue Location”–tagged location: Outpatient Clinic, which is a child of Ubuntu Hospital. The hierarchy looks roughly like:

Ubuntu Hospital  (Visit Location)
├── Outpatient Clinic  (Queue Location)
├── Inpatient Ward
├── Ward 1 / Ward 2 / Ward 3
Site 1 … Site 50  (siblings of Ubuntu Hospital, unrelated)

Without the fix:

  • Log in to Site 7 → list shows Outpatient Clinic’s entries anyway.
  • Log in to Inpatient Ward (sibling of Outpatient Clinic) → list shows Outpatient Clinic’s entries.
  • Log in to Outpatient Clinic → list shows Outpatient Clinic’s entries.

Three different sessions, identical list — i.e. the location filter is never actually applied.

Screenshot: Site 7 login showing Outpatient Clinic entries (the bug case)

Proposed behavior

After confirming the rough shape with @ibacher and @nethmi, the rule I’d like to land on is:

  1. Self first. If the session location is itself tagged “Queue Location”, auto-select it.
  2. Else closest in the hierarchy. Resolve to the nearest queue-tagged ancestor, descendant, sibling, or cousin of the session location. Implementation note: the current PR does this by walking parentLocation to the topmost ancestor and querying Location?_tag=queue location&partof:below=<root> plus a self-lookup, which covers the common 2–3 level facility hierarchy.
  3. Else empty. If nothing in the session location’s subtree is a Queue Location, the list is empty and no /queue-entry request fires (rather than silently falling back to a global query).

Expected on dev3 after the fix:

Login Resolves to List
Outpatient Clinic self Outpatient Clinic’s queue
Inpatient Ward / Ward 1–3 sibling: Outpatient Clinic Outpatient Clinic’s queue
Ubuntu Hospital child: Outpatient Clinic Outpatient Clinic’s queue
Site 7 (no queue kin) empty

Open questions for the community

I’d particularly like input on these:

  1. Multi-facility deployments. Some implementations have a top-level container (e.g. Country / Region) that holds multiple independent facilities, each with its own Queue Location. Walking up to the topmost ancestor would surface queue locations from sibling facilities. Is “strict closest” (climb level-by-level and stop at the first ancestor whose subtree contains any Queue Location) the right semantics, or do implementations typically prefer the broader “everything in this country/region” view?

  2. Empty-state UX. When a user logs in somewhere with no resolvable Queue Location (e.g. an admin/back-office location), should we:

    • show a blank list with no message (current PR behavior),
    • show an empty-state notification (“No queue locations for your login location”),
    • or fall back to letting the user pick from all Queue Locations system-wide?
  3. Consistency with useActiveVisits. The “Checked in patients” metric is powered by a different hook (useActiveVisits) that scopes strictly to sessionLocation.uuid — it ignores the location dropdown entirely. After the fix, the Queue list and “Waiting for” card follow the resolved queue location, but “Checked in patients” still follows the literal login location. So on the same dashboard:

    • Login to Inpatient Ward → Queue list shows Outpatient Clinic patients (resolved), but Checked-in patients = 0 (no visits at Inpatient Ward). Should “Checked in patients” also follow the resolved queue location for consistency, or is the current behavior (active visits at the physical login location) intentional?
  4. Queue-Location tag enforcement on the backend. Separately, queues can currently be created at untagged locations. Is this worth a parallel ticket on openmrs-module-queue? If so, what should happen when someone tries to create a queue at an untagged location — reject it, auto-tag it, or warn?

CC: @veronica @ibacher @nethmi @dennis

2 Likes

it’s a queue scoping / sessionLocation mismatch.

don’t complicate resolution:

self if queue-tagged else only queue-tagged descendant else empty (no lateral/parent fallback, avoids cross-facility leaks)

show an explicit empty state, not a blank UI.

also fix inconsistency: useActiveVisits uses physical location while queue list uses resolved queue location – that mismatch will confuse users. or tell the two contexts apart.

and yes, enforce queue-tagged location creation on backend, otherwise frontend fixes won’t stick.

1 Like

One thing I’d like to point out here, is that there is a location filter on the service queues home.

This dropdown renders all queue locations in the instance. The reason it wasn’t visible before was because there was only one demo location tagged in dev3, and the dropdown is set to conditionally render only if there is more than one queue location.

So right now, what happens is, if the user is logged in to a location that is tagged as a queue location, that location gets set as the selected location. Else, the first location in the queue location list gets set as the selected location and the queue entries get filtered by that selected location.

1 Like

@fanderson @chibongho would you have any input on this :slight_smile:

Some terminologies, for the purpose of this post:

  • session location: the location that the user has logged into
  • session’s visit location: the closest ancestor to the session location (or the session location itself) that is tagged as a “Visit Location”; might not exist
  • session’s queue location: the closest ancestor to the session location (or the session location itself) that is tagged as a “Queue Location”; might not exist

Resolve to the nearest queue-tagged ancestor, descendant, sibling, or cousin of the session location.

Just to confirm, this is for pre-selecting the option in the location dropdown, right? I think considering the ancestors makes sense, but including the other relationships gets messy. What would happen if there are multiple equal-distance descendants, siblings or cousins with “Queue Location” tag? I propose we just pre-select the location dropdown to the session’s queue location (so we only consider ancestors).

Regarding the open questions:

  1. For multi-facility deployments, we have a similar pattern in the dispensing app, where we show a location filter, although it’s disabled in the refapp. See its config. We have a location tag config that filters the options of the location dropdown to only locations with that tag. Recently, we also added a restrictToVisitLocationDescendants config; if true, it further limits the options in the location dropdown to only locations that are descendents of the session’s visit location; if false, all locations options with the right tag are shown in the dropdown. I think we can do the same thing here.

  2. I want to make a distinction between what location options are available in the dropdown vs what location option is pre-selected. For what options are available, I think it should be determined by the tag config and, if the restrictToVisitLocationDescendants config is true, the session’s visit location. For what we pre-select in the dropdown, we should default to the session’s queue location if it exists, or “All” if not. Keep in mind that the “All” option here is still subject to the location options filtering by tag and restrictToVisitLocationDescendants configs. So “All” means all location options available in the dropdown, and does not mean all locations literally.

    I think the table showing the “No patients to display. Check the filters above” message when there are no patients based on the user’s location + service filtering is fine.

  3. The current behavior is probably unintentional. To be honest, I’m not sure if that metric is well defined. Should we count patients with active visits but not in queues? Do we still count patients with active visit with visit location == session’s visit location, even after we apply stricter location filtering in the dropdown?

    Related, I think we should always make the queues table show the pagination bar (which also shows the row count) at the bottom.

  4. The dispensing app kind of gets around this by adding a location tag config, and making it the responsiblity of the frontend configuration person to make sure all the queues are displayed there.

cc: @fanderson @mseaton @mogoodrich

2 Likes