Skip to content

Clinic workflow fixes: vitals, referrals, CAD registration and workspace cleanup - #23

Open
dadsena01 wants to merge 13 commits into
bwhtech:mainfrom
dadsena01:fix/clinic-workflow-and-staff-onboarding
Open

Clinic workflow fixes: vitals, referrals, CAD registration and workspace cleanup#23
dadsena01 wants to merge 13 commits into
bwhtech:mainfrom
dadsena01:fix/clinic-workflow-and-staff-onboarding

Conversation

@dadsena01

Copy link
Copy Markdown
Contributor

This covers a batch of clinic workflow work that had been sitting uncommitted: nurse vitals recording, doctor referrals with a printable letter, a richer shared patient-details view, a quick-create page for one-off sessions, a reworked CAD registration form, and a pass through every workspace shortcut fixing the ones that pointed at the wrong thing or showed nothing at all.

Nurse can now record height, weight, temperature, pulse, SpO2 and blood pressure during a visit, with BMI calculated automatically. Doctor can capture chief complaint, past history and allergy history on any action that closes out a visit, and can refer a patient elsewhere with a printable referral letter. Both of those feed into the shared patient-details popup so a doctor or nurse sees the full picture, not just what was captured at registration.

The CAD registration form got reworked: Sex, Country, Native State and Occupation are quick-tap buttons now instead of free-text fields that could crash registration on a typo. Age-only registration (common for migrant workers who know their age but not their exact birthday) now estimates the date of birth as January 1st of the birth year instead of today's exact month and day minus N years, which read as a fake precise date. Native District is a proper dropdown tied to the state, and now has real district lists for all 36 Indian states and union territories instead of just 6.

Screenshot of the reworked form:

CAD registration form

Also fixed a bunch of desk-level stuff: the CAD/Doctor/Nurse icons on /desk that weren't showing up for those roles, rounded corners that were broken sitewide because the CSS was referencing a variable name that doesn't exist, the "Patients Seen Today" dashboard number counting patients who hadn't actually finished their visit yet, and a pass through every workspace shortcut checking each one against what it actually links to (a few pointed at the wrong doctype, a few pointed at doctypes nothing ever writes to, one showed 34 items when only 5 are real medicines).

The district data for the 30 states beyond the original 6 is compiled from general knowledge of India's administrative divisions, not an official register, so it's worth spot-checking against the Census of India before fully trusting it, especially for Madhya Pradesh, Andhra Pradesh, Telangana and Rajasthan, which have all had their districts officially reorganised in the last few years.

All 209 tests pass.

Frappe seeds a Desktop Icon per public workspace only once, at creation
time, and never re-copies the workspace's roles or icon after that. Every
tile ended up System Manager only, so field staff landed on /desk with
nothing to click. CAD's workspace also had no icon set when its tile was
seeded, so it kept rendering blank even after cad.json got one later.

Replaces the old single shared 'App' tile (which only ever led to
Frappe's 'Icon is not correctly configured' dead end) with syncing each
workspace's own per-role tile on every migrate, and fixes the workspace
lookup itself: it was filtering on Workspace.app, which is only as good
as whatever app happened to be active in the Desk UI when someone
created the record by hand, wrong for most of these. module is what
each workspace's own fixture actually sets.
Every card/box on the Doctor, Nurse, My Schedule, Staff Onboarding and
New Schedule pages referenced var(--radius-md) / --radius / --radius-full,
none of which exist as Frappe design tokens — the real names are
--border-radius-md / --border-radius / --border-radius-full. An unset
custom property resolves to nothing, so border-radius was computing to
its default (0) everywhere it was used; every one of these boxes has
been rendering square-cornered instead of rounded.
New record_vitals endpoint + a dialog on the nurse queue card: height,
weight, temperature, pulse, SpO2 and blood pressure, each optional but
at least one required, all rejected if zero or negative. BMI is
recalculated from height/weight whenever both are present. Only
allowed while the patient is actually with the nurse (Awaiting Test or
Awaiting Medicine) — matches the same session-ownership gate as the
rest of this page.
… letter

order_test, prescribe_medicine and complete_encounter now all accept
chief complaint, past history and allergy history, saved onto the
encounter regardless of which action closes out the visit.

complete_encounter also takes an optional referral (where to, who to,
why, priority) and creates a real Referral record when given one — both
where and why are required together, so a half-filled referral can't
be saved. New Bandhu Referral Letter print format plus
get_referral_letter_html, which crosses the same permission boundary
get_patient_card_html already does on the CAD page: Referral is System
Manager only in DocType permissions, and load_owned_encounter is what
proves the caller may see this particular patient before the render
runs on their behalf.
…ails

The shared patient-details dialog (Doctor and Nurse queue cards) now
shows this visit's own vitals instead of only what the patient carried
in from registration, plus Pulse/SpO2/Blood Pressure and Chief
Complaint/Past History/Allergy History sections. A visit's own reading
wins over registration data whenever the nurse has recorded one, since
that's what's clinically true right now.

Doctor and Nurse also get direct read/print/report permission on
Patient Encounter (permlevel 0) so this no longer has to go through
ignore_permissions to render.

Bumped session_ui.js's cache-busting ?v= — app_include_js raw file
paths aren't auto-versioned, so without this browsers keep serving the
old file after a change.
New Schedule only ever covered recurring camps (Weekly/Fortnightly/
Monthly) — starting a single ad hoc session still meant the full
20-field Bandhu Clinic Session Desk form. New Session is a one-screen
form instead: Clinic autofills Project/Vehicle the same way the
schedule wizard does, a clash warning reuses find_assignment_clashes
against the one date instead of a generated list, and Create just
inserts a Planned session with no session_schedule — that blank field
is what marks it as ad hoc rather than schedule-owned, so it can't
collide with the nightly generator's idempotency key.

require_scheduling_access, practitioners_by_role, association_maps and
clock_value move out of new_schedule.py into the shared
session_schedule module so both pages use one implementation instead
of two copies that would drift apart.
…or data

Registration form: Sex/Country/Native State/Occupation render as quick-tap
tab groups instead of free-text inputs, so a typo can no longer crash
registration with a Link-validation error the way native state and sector
used to. Full Name, Native State, Sex and the Age/DOB pair are marked as
actually required, matching what register_patient enforces server-side —
Age/DOB gets a plain-language note instead of a star on either field,
since only one of the two is required, not both.

DOB estimate from age alone: was today's exact month/day minus N years,
which reads as a real recorded birthday. Now Jan 1 of the calculated
birth year, so it's honestly an estimate rather than a fabricated date
— matters for migrant workers who know their age but not their
birthday.

Native District: was a free-text field wired to a native <datalist>
positioned by the browser with no CSS hook available to fix it. Now a
plain select next to the state, disabled until a state is picked,
populated from state_districts.py — matching how the state and country
'Other' pickers already work.

Only 6 of India's 36 states/UTs ever had a district list; the other 30
returned nothing at all, in a state field that already accepted 36
states via 'Other'. Filled in the rest — general knowledge of India's
administrative divisions, not an official register, so worth a
spot-check against the Census of India before relying on it, especially
for Madhya Pradesh/Andhra Pradesh/Telangana/Rajasthan which have all
had district boundaries officially reorganised in the last few years.

Sectors gets the same is_major_sector split the state master already
had: five CMID-specified sectors as quick taps (two renamed in place
via rename_doc, not delete+recreate, so any patient already linked
carries forward), the rest reachable only from the full Desk picker.

Full Name, Native District and ABHA ID each rendered alone in a row of
the form's 2-column grid, stuck at half width with the other column
empty next to them — now span the full row like the tab groups already
did.
Went through every workspace shortcut and checked its label against
what it actually links to and what data is really behind it:

- Doctor's 'Patient Queue' pointed at Patient Encounter, not the real
  Patient Queue doctype the Bandhu workspace's own shortcut of the same
  name correctly uses.
- Bandhu's 'Vehicle log' linked to the Vehicle master, not a log — the
  real logs (Usage, Refuel) sit right beside it. Relabelled to
  'Vehicles'.
- Bandhu's 'Start Consultation' created a bare Patient Encounter,
  bypassing sync_to_queue, the session link and the workflow-state
  machine entirely. Now opens the CAD page, the real entry point.
- Bandhu's 'Staff Log' and Nurse's 'Medicine Movement'/'Medicine
  Dispense' pointed at doctypes with zero rows and no code anywhere
  writing to them — removed.
- Pharmacist's 'Medicines' showed all 34 Items in the system, 29 of
  them not medicines at all. Now a URL shortcut to /app/item?item_group=
  Drug, which a DocType-type shortcut's stats_filter can't do (that
  only drives the badge count, not what the list opens to).
- Inventory's three shortcuts (Asset/Asset Movement/Asset Repair) are
  ERPNext fixed-asset accounting, unrelated to a mobile clinic's actual
  medicine/vehicle/equipment inventory, all zero rows. Removed.
- Admin's 'Roles' badge filter referenced a Helpline Staff role that
  doesn't exist in this system. Dropped from the filter.
- Trailing-space label typos on Admin's 'Site' and (already fixed
  separately) Bandhu's old 'Start Clinic Session'.
Filtered on encounter_date = today only, so a patient still waiting or
with the doctor counted as 'seen' the moment they registered. Added
custom_workflow_state = Completed, matching the filter the CAD page's
own 'Completed Patients' quick list already uses correctly.
Two long explanatory comments removed at the user's request. The
page-width/page-height landmine they documented (non-standard CSS
properties Chrome's PDF generator reads directly, real card size
verified by rendering to PDF and measuring the output) stays recorded
in this app's own project notes instead of inline.
restrict_other_app_desktop_icons filtered on Desktop Icon.app != 'bandhu_app'
to decide which icons belong to other apps and should be locked to System
Manager. Every one of this app's own 9 icons has app blank — the exact
same landmine sync_bandhu_desktop_icons already had to work around on
Workspace.app — so this function was classifying CAD/Doctor/Nurse/Admin/
Bandhu/Dashboard/Inventory/Pharmacist/Referrals as foreign and locking
all nine back to System Manager only. Both functions run in the same
after_migrate hook, in sequence, so this undid sync_bandhu_desktop_icons's
fix immediately after it ran, every single time — not caught in the
earlier commit because a role was only ever spot-checked once via
frappe.get_doc right after running sync alone, never after both hooks
ran together, and not through an actual browser session as that role.

Now filters on link_to against this app's own workspace names (via
Workspace.module, the same reliable check the sibling function already
uses) instead of the icon's own app field.

Verified live as Nurse, CAD and Doctor (each now shows exactly their own
tile) and as Administrator (unchanged, still sees the full grid) — not
just re-read from the database this time.
CI builds a real fresh site (bench new-site + install-app, no setup
wizard), which has zero Gender, Appointment Type, Indian State and
Sectors records, plus no Clinic/Site/Unit/Bandhu Projects/Item for a
dozen test classes to grab. All of it only ever worked on bandhuapp.local
because that dev site carries leftover data none of it was ever actually
seeded by.

- seed_default_genders, seed_default_appointment_type: new, wired into
  after_install and after_migrate. "Walk-In" is a hardcoded Property
  Setter default on Patient Encounter, so every encounter this app
  creates needs it to exist.
- seed_indian_states now also covers Kerala and the 6 major migrant-source
  states, not just the other 29 -- also never seeded by app code, just
  manually added on the dev site once.
- new baseline_test_fixtures.py, wired into every test class that assumed
  Clinic/Site/Unit/Bandhu Projects/Item already existed.
- fixed test_doctor_form.py: its tearDown calls frappe.db.rollback() after
  every test, which was also wiping the baseline setUpClass had just
  created since nothing had committed in between.
- test_nurse_form.py's hardcoded _Test Stock Item doesn't exist on a
  fresh site either, switched to the shared baseline Item.

209/209 tests pass, ruff and semgrep clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant