GSoC 2026: Service Queues — Progress So Far

Hi everyone! I’m Ujjawal, working on giving the Service Queues app some much-needed TLC in OpenMRS O3 this summer as part of GSoC 2026.

I’ve been posting weekly write-ups on Medium with more narrative detail than what’s below, link at the end if you want the full story behind any of these. This post is meant as a single running summary of progress so far, and I’ll keep updating it week by week as things move forward.

Jira Epic: O3-5664 — Service Queues


The Project, in Brief

Service Queues helps outpatient clinics track who’s waiting, how long they’ve been waiting, and what they’re waiting for. It basically works but it’s been missing a lot of love: UI inconsistencies, hardcoded assumptions that break at deployments different from the reference app, unreliable backend APIs, and flows that strand users mid-task.

The goal is to fix all of it - frontend, backend, and everywhere in between. So the app is reliable, extensible across different deployments, and pleasant to actually use, for both clinic staff managing the queue and patients waiting in it.


Progress So Far

Bonding Period

Spent most of bonding mapping out how the Service Queues flows were supposed to work versus how they actually behaved, turned out more was broken than working, which gave a clear, well-scoped starting point once coding began.

Week 1 — First Fixes

  • #2540 (merged) — Vitals and Triage form buttons were redirecting to the patient summary instead of opening the form. Both now open inline in a side panel.
  • #2541 (merged) — Patient notes were rendering twice in the Previous Visit tab.
  • #2543 (merged) + content-referenceapplication-demo#74 (merged) — The Service Queues screen rendered blank on default installs because nothing created the Visit Queue Number visit attribute. Fixed by defaulting the config and adding the attribute type via the content package/Initializer.
  • #2550 (open) — The queue wasn’t filtering by the user’s login location at all; switching locations had no effect on what was displayed. Still under discussion here.

Week 2 — Hardcoded Assumptions & Performance

  • #2555 (open) — The “calling” status label and Drug Order concept UUID were hardcoded in the frontend. Made both configurable via the config schema.
  • #2559 (merged) — Replaced hardcoded hex colors with the O3 styleguide’s design tokens so the app themes correctly.
  • #2564 (open) — The patient-facing queue screen was polling every 3 seconds nonstop, even on unattended waiting-room monitors. Added activity- and visibility-aware polling.
  • queue#115 (open) — Three backend fixes: wrong ORM mapping on queueComingFrom, a duplicate DB lookup in AbstractBaseQueueDaoImpl.get(), and a null-pointer crash in QueueEntryResource.getDisplay.
  • queue#116 (open) — Added missing indexes to queue_entry on queue_id, patient_id, started_at, and ended_at.

Week 3 — Closing My Own PR

Originally built a dedicated /rest/v1/queue-entry-summary endpoint (queue#114) to avoid the deep custom:() representation the queue table was loading through, which pulled the entire object graph off a patient’s visit for a table that displays maybe 5% of that data. After review discussion here, it became clear the same problem could be solved without a new API surface:

  • #2583 (open) — Trims the frontend’s custom:() representation to only the fields the table actually renders.
  • queue#117 (open) — Adds a real previous_queue_entry column with @BatchSize, fixing an N+1 for every consumer, not just the table.

queue#114 was closed in favor of these two more targeted fixes.

Week 4 — Scoping the Next Round

No PRs this week — spent it turning a list of vague improvement ideas (thanks, Ian!) into eight precisely-scoped tickets under the epic: O3-5758, O3-5759, O3-5760, O3-5761, O3-5762, O3-5763, O3-5764, O3-5765.

Week 5 — Turning Tickets Into Code

  • patient-chart#3419 (open) — Exposes the patient chart’s VisitSummary as a reusable extension.
  • #2600 (open) — Consumes that extension in Service Queues, replacing the queue’s bespoke (and drifted) Current/Previous visit widgets with the same component the patient chart uses. Addresses O3-5763.
  • #2607 — Fixed the Average Wait Time metric tile, which was calling the wrong endpoint entirely and likely never showed a real number. (Superseded by #2615 below — closing this one.)

Week 6 — Visible Progress

  • #2608 (open) — Fixes O3-5762: starting a visit from the add-to-queue flow now returns you to that form instead of stranding you on the patient search list, via an opt-in flag on the shared “Start visit” component so other consumers are unaffected.
  • #2611 (open) — Fixes O3-5769: “Move” and “Transition” row actions were functionally identical (same modal, same endpoint); combined into one.
  • #2615 (open) — Fixes O3-5760: reworks the dashboard header to match the existing design — current location/service shown inline with a “Change” action instead of separate dropdowns, plus fixes to default location resolution, the appointments-today count, and the average-wait-time metric.

Where Things Stand

Merged: #2540, #2541, #2543, content-referenceapplication-demo#74, #2559

Open for review: #2550, #2555, #2564, queue#115, queue#116, #2583, queue#117, patient-chart#3419, #2600, #2608, #2611, #2615

Superseded/closed: queue#113, queue#114, #2607

More detail on the reasoning behind each of these, especially the ones that took an unexpected turn is on my Medium blog: ujjawalprabhat.medium.com

Will keep this thread updated as the weeks go on. Thanks for following along! :seedling:

A big thank you to my mentors — @nethmi, @jwnasambu and @ibacher for the guidance, patience, and all the review feedback that’s shaped these fixes into something better than what I initially had in mind. And thanks to the wider @openmrs community for the reviews, discussions, and context along the way. It’s made this project genuinely enjoyable to work on.

2 Likes

A video walkthrough of the same here. :slight_smile:

2 Likes

Week 7 & 8 Update

Week 7 — Privileges for Two Audiences

  • #2625 (open) — Fixes O3-5759: the wait-time column now changes color once a patient has been waiting past a configurable threshold (default 2 hours), so long waits are visible at a glance instead of blending in.
  • queue#118 (open) — Adds three new privileges: App: Service Queues Clinic Administrator, App: Service Queues Clerk, and App: Service Queues Clinician. Not enforced on any backend service, they exist purely so the frontend can ask “who is this user, in the context of this app?” Distributions decide which roles get which privilege.
  • #2626 (open) — Fixes O3-5764: the home screen now checks those privileges. A Clerk or Clinician who isn’t also a Clinic Administrator lands on a new FocusedQueueView — same header, metrics, and table, but filters hidden and location locked to their session location. Admins keep the full dashboard. Falls back to the existing dashboard for everyone until queue#118 is released and privileges are attached to roles, so it ships safely regardless of merge order.

More detail on the reasoning behind O3-5764 — it took a few weeks to figure out what the actual problem even was — on Medium: Finally Figuring Out Who This Screen Is For

Week 8 — Closing Out Two More From the List

  • queue#119 (open) — Fixes O3-5765: adds AutoCloseQueueEntryTask, registered alongside the existing visit-close task. Runs every minute and, once the clock passes a configured time, closes any queue entry that started on or before that time. Two new global properties control it — what time to run (default end of day) and which queues it applies to (blank = all).
  • #2632 (draft) — The frontend half of O3-5765: removes the manual “Clear queue entries” button, its confirmation modal, and the orphaned translation strings, now that clearing happens automatically. Depends on queue#119 landing first, so it’s staying in draft until then.
  • #2633 (open) — Fixes O3-5761: “Add patient to queue” used to show a blank panel until you typed a search. Now it lists patients who already have an active visit at the selected location but aren’t in any queue yet, before you type anything. Typing still runs the full search as before.

Full write-up on Medium: Two Down From the List

Week 10

Mostly review follow-up this week, but three new PRs went up, all surfaced while going back through older work rather than from new tickets, plus a design out for community feedback.

  • content-referenceapplication-demo#79 (merged) — Wires the three privileges from queue#118 onto the demo’s existing roles (Doctor/Nurse → Clinician, Registration Clerk → Clerk, System Administrator → Clinic Administrator), so the Week 7 privilege-gated view has something real to check against in a deployment.

  • queue#120 (merged) — Fixes O3-5760: QueueUtils.computeAverageWaitTimeInMinutes guarded against an empty entry list but not against a non-empty list where nothing had actually finished waiting yet, leaving the denominator at zero and the average wait time metric rendering NaN. Now returns null instead, which the frontend already handles gracefully.

  • patient-chart#3509 (open) — Fixes O3-5763: VisitNotesForm pulled its visit context from usePatientChartStore, which only the patient chart populates. Launched from Service Queues, visitContext came back null, and the backend’s fallback visit-assignment logic picked a visit, not necessarily the one being viewed. Splits the form the way the vitals form already handles this, taking visitContext explicitly as a prop and exporting it as a reusable workspace.

Also put together a design for a dedicated Clinic Administrator screen and posted it for community feedback — a clinic-wide monitoring view, addressing O3-5770, that shows every queue at a glance instead of one at a time. It’s the natural next step after Week 7’s privilege model.

Full write-up on Medium: The Week of “While I Was In There”

Week 11

Only one new PR this week (patient-chart#3534) — which makes the visit summary Timeline expandable so you can view what was actually recorded in an encounter without leaving it and retires the now-redundant Encounters tab (with its print and embedded-form-view functionality ported over first, so nothing’s lost).

Most of the remaining work is follow-up at this point, getting the stack of open PRs through review and merged.

Full write-up on Medium: One Last Feature, Then the Long Tail

Week 12

The Clinic Administrator screen design from a couple weeks back is now real code: #2681 adds the clinic-wide monitoring view for anyone holding the App: Service Queues Clinic Administrator privilege, clinic totals up top, then one row per queue sorted worst-first, so whichever queue needs attention surfaces itself. Monitoring only, clicking into a row opens that queue’s existing view unchanged.

This was the last genuinely new piece of surface area the project needed. Most of what’s left from here is follow-up…getting the stack of open PRs through review and merged.

Full write-up on Medium: The Design Becomes Real

Will keep this thread updated :seedling: