Clinic workflow fixes: vitals, referrals, CAD registration and workspace cleanup - #23
Open
dadsena01 wants to merge 13 commits into
Open
Clinic workflow fixes: vitals, referrals, CAD registration and workspace cleanup#23dadsena01 wants to merge 13 commits into
dadsena01 wants to merge 13 commits into
Conversation
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.
dadsena01
force-pushed
the
fix/clinic-workflow-and-staff-onboarding
branch
from
September 2, 2026 13:10
d2d3ba3 to
1f57efb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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.