- Add UserProfileModel and migration for user profile data
- Enhance User Management views, controller, and doctor/nurse search integration
- Refactor handleAuthError to separate 401 session expiry from 403 access restriction
- Apply granular permission checks to sidebar navigation links
- Open Bed Status view for all authenticated users
- Support GET and POST on charges item routes and exempt billing charges from CSRF desync
- Add Day Care (<24h) and Emergency (Casualty) admission pathways with prefixes DC- and ER-
- Add dedicated physical wards, ESI 5-level triage, MLC tracking, and PADSS day care discharge
- Implement audited 'Convert to IPD' workflow with SBAR handover and automated bed transfer
- Support unified IPD billing with dedicated group headers for Day Care and Emergency charges
- Redesign Hospital Admission Desk with executive card layout and modern triage controls
- Add comprehensive user documentation and SVG flowchart in public/help.html
- Completely remove legacy patient_master.p_lname column from database and application code
- Use COALESCE to check both bed_master.current_ipd_id and bed_assignment_history
- Join with bed_assignment_history where released_date IS NULL for active beds
- Handles cases where bed is assigned in history but current_ipd_id not set
- Fixes bill print showing blank Bed No when assignment exists in history
- Add bed_master join to fetch current bed assignment via current_ipd_id
- Add ipd_master_doc_list and doctor_master joins to fetch assigned doctors
- Use GROUP_CONCAT to handle multiple doctors in single query
- Fixes bill print displaying empty Bed No and Doctor Name fields
- Implemented automatic bed release on patient discharge
- Added bed transfer functionality in nursing workspace
- Added date/time tracking for bed assignments with duration calculation
- Fixed bed_master.current_ipd_id as source of truth for occupancy
- Created data fix scripts for existing records
- Added bed assignment history with duration display (hours/minutes)
- Fixed display issues in bed assignment tab
- Added route for bed transfer endpoint
- Supports custom assignment datetime for backdated entries
- Automatically marks previous bed as released on transfer
Root cause: 50k+ invoices had insurance_case_id='0', and MySQL string comparison '0'='C26060004997' matched (both convert to numeric 0).
Fix: Exclude NULL/empty/'0' insurance_case_id before comparison in:
- getOrganizationCaseInvoiceRows() union query
- updateOrgTotals() aggregate queries
Result: Case C26060004997 now returns 9 rows instead of 56,786 (memory crash fixed)
- Create user_settings table to store individual user preferences
- UserSettings model for get/set/delete user setting values
- Home::myProfile loads user settings with hospital defaults fallback
- Home::myProfileSave persists user settings to DB
- my_profile.php adds Sidebar Auto-Hide Delay field (0-60 seconds)
- welcome_message.php checks user settings first, then hospital default
- Setting value 0 = auto-hide disabled; blank = use hospital default
- Extensible table design for future user settings (color theme, etc)
- Safe delete for empty IPD charge groups with CSRF-safe AJAX
- Migration: add sort_order to ipd_item_type (backfilled)
- Sort order UI on create/edit/list views; persist in controller/model
- Up/Down swap buttons on group list (AJAX swap endpoint + CSRF refresh)
- Fix 500 on edit screen: restore missing getItemTypeById() in ItemIpdModel
- IpdBillingModel: propagate sort_order ordering to ipd-charges and bill-details tabs
- Billing IPD Charges tab: Bedside Clinical/Nursing Charge and Doctor Visit Charge panels now collapsible, start collapsed
- Add OPD Validity (Days) field in Doctor add/edit forms\n- Save/update doctor_master.opd_valid_no_days from Doctor module\n- Use hospital_setting fallback keys when doctor validity is blank/zero\n- Apply fallback consistently in OPD showfee, print expiry, and running_opd lookup window\n- Supports hospital-wide defaults while preserving doctor-specific overrides
OpdModel.php:
- running_opd_id lookup now uses doctor's configured opd_valid_no_days
instead of hardcoded 4 days (resolveRunningLookupDate helper)
- Doctors with validity > 5 days now correctly link running OPD back
to the original paid OPD even on days 5..N of the window
Opd.php (buildOpdLetterPrintData):
- For running OPD entries (running_opd=1 or opd_fee_type=3), expiry
display now shows "OPD Start Date: [paid visit] | Valid Upto: [paid
visit + validity]" using old_opd record — mirrors Opd_print_1 legacy
behavior and prevents validity window from advancing with each visit