Conversation
- Add System Manager staff onboarding page: creates User + Healthcare Practitioner in one call instead of four manual Desk steps - Convert CAD/Doctor/Nurse from website pages to Desk Pages with full Desk chrome (sidebar, search, notifications) - Grant Doctor/Nurse/CAD roles read access on Page doctype - Gate patient queueing on clinic session status = In Progress, so a patient can no longer reach the doctor before the nurse starts session - Add Details/Order Test/Prescribe Medicine dialogs for doctor, and Enter Results/Dispense dialogs for nurse, carrying real structured clinical data instead of a bare state flip - Add doctor get_session_status/session bar for parity with CAD/Nurse - Add CAD/Doctor/Nurse/Onboard Staff shortcuts to the Admin workspace
Restrict the CAD, Doctor and Nurse workspaces to their own role plus System Manager, and the remaining workspaces to System Manager only. Framework, Quality and Marley Health are Desktop Icon records owned by frappe, erpnext and healthcare, so they cannot be restricted by editing those apps. desk_visibility runs on after_migrate instead, because each app re-syncs its own icon fixture on every migrate and would otherwise wipe the restriction. Clicking a CAD, Doctor or Nurse workspace icon now routes straight to the working page rather than an icon grid. The include path carries an explicit version, since app_include_js raw paths are not cache-busted by the framework and browsers keep serving the previous file.
Clinic ID is now LSG(2) + Unit(1) + Year(2) + Serial(5), replacing the BMC-##### series for newly registered patients. IDs already issued are left untouched, and both formats stay searchable. The serial resets per calendar year and runs global across every LSG and unit. Scoping it per LSG or unit would tie a permanent identifier to attributes that get corrected and reorganised, forcing an issued ID to either change or start lying. It is drawn from the Series counter rather than max()+1, which races when two front desks register at once, and it throws instead of widening past five digits. lsg_code and unit_code hold text like LSG-EKM-KLM, so the numeric components live in new fields alongside them. Both become immutable once any ID has been issued, because every printed card embeds them. Bandhu Clinic Session gains a unit link. Nothing in the registration path could resolve a unit before; deriving it from Unit.cad breaks as soon as one CAD covers two units. register_patient now takes the session and is gated on session access rather than role alone, since the session decides which codes land in a permanent ID. The QR encoded an API URL, so scanning a card produced a JSON page. It now carries the bare Clinic ID, which is what a USB barcode scanner needs and what a phone camera can show a human. A patch reissues the images for existing patients. New Bandhu Patient Card print format at CR80 size, reachable from the CAD screen through a whitelisted endpoint: the role holds no Patient print permission, so /printview refuses it. Scanning a card jumps straight to the patient on an exact match, and every queue row carries the grouped Clinic ID and its own print action.
Captures work that had accumulated uncommitted across several sessions, plus this round's security and correctness fixes. Scheduling - Bandhu Session Schedule (+ weekday child, Bandhu Settings single) and utils/session_schedule.py generate recurring camps weekly, fortnightly or monthly. Idempotency keys on (schedule, date), so a camp cancelled for a holiday is not regenerated by the nightly job. - page/new_schedule: guided Where/When/Who/Check wizard, with clash warnings when a doctor, nurse or vehicle is already committed. - page/my_schedule: field staff see the camps they are on the team for, drivers included. Cancelled camps are shown and badged, not hidden. - First use of scheduler_events in this app. Dashboard - Six number cards and a weekly chart on the Dashboard workspace, following the Number Card + Dashboard Chart pattern used elsewhere in the org rather than a custom page. Security and correctness - Escape patient_name, mobile and the clinic ID in the patient card print format. Frappe's Jinja environment has autoescape off, and the card is rendered into a same-origin window, so a name entered at registration could run as script in the session of whoever printed it. - register_patient now requires a running camp, sharing one gate with create_encounter. The camp resolves the LSG and unit codes baked into a permanent, printed Clinic ID. - Nurse start/end camp is now a state machine: no reopening a closed camp, no opening one dated another day, nothing on a cancelled camp. - sync_to_queue survives two front desks registering the same patient at once. Patient Queue.patient is unique and DuplicateEntryError is not a ValidationError, so the existing handler never caught it and the whole registration rolled back. Display - Ages read 52y / 8mo / 12d instead of Healthcare's three-line "52 Year(s) 4 Month(s) 16 Day(s)". - Camp site shows its name, not its record id. - Queue tables no longer clip the last patient behind a 360px box. 106 tests pass.
Whitelisted methods no longer return {"success": True} — the absence of an
error is the success signal, so the client stops branching on a flag that only
ever held one value. frappe.throw's explicit frappe.ValidationError argument
goes with it; the default is the same exception.
Each Desk page's styles move out of the JS template string into a sibling
.css file.
|
Why this was closed (2026-08-26): consolidated, not abandoned. This PR's commit Verified before closing with Where the work lives now:
If you are here from a link or a changelog and want the history of this specific change, |
Applies the review feedback from #10.
Whitelisted methods no longer return
{"success": True}— the absence of an error is the success signal, so the client stops branching on a flag that only ever held one value. The explicitfrappe.ValidationErrorargument tofrappe.throwgoes with it; the default is the same exception.Each Desk page's styles move out of the JS template string into a sibling
.cssfile.Depends on the scheduling PR, since it also restyles
my_scheduleandnew_schedule. Merge in order.