Commit Graph

685 Commits

Author SHA1 Message Date
0c85dddd43 Investigation profile: preserve select2 item order in edit panel 2026-07-02 18:43:34 +05:30
0a48fa6d2c OPD investigation list: order by id instead of name 2026-07-02 18:24:33 +05:30
6288c626fc mPDF: normalize numeric font-weights across template PDF renderers 2026-07-02 10:27:46 +05:30
1abf572a14 OPD letter: add HTML debug endpoint and placeholder style controls 2026-07-02 10:09:45 +05:30
e85bfd85e1 OPD template: split opd fee into amount and description placeholders 2026-07-02 09:40:25 +05:30
0f8bd43e72 Fix ABDM M3 HIU ID mapping, polling guards, and migration compatibility 2026-07-02 00:55:05 +05:30
3d40642116 Add ABDM M3 HIU workflows, routes, UI, and runbook docs 2026-07-01 17:37:53 +05:30
14a9d851ad ABDM: force gateway push from OPD modal and treat timeout as queued when bridge already succeeded 2026-06-30 19:15:29 +05:30
c310221961 ABDM: use configured HFR for EAtria connector and avoid submit timeout HTML 500 2026-06-30 18:49:37 +05:30
3072639cd5 Revert "ABDM: fix local submit fallback, HFR runtime usage, status sync, and link-token retry"
This reverts commit e08c18f5b2.
2026-06-30 18:11:34 +05:30
e08c18f5b2 ABDM: fix local submit fallback, HFR runtime usage, status sync, and link-token retry 2026-06-30 18:09:55 +05:30
ed48a447e5 ABDM M2: add push-sync outbox, worker, and FHIR generators 2026-06-27 01:53:44 +05:30
e651b18a01 ABDM: guard repeat OPD submits and dedupe health records 2026-06-27 00:32:14 +05:30
db7ba044b1 ABDM task board: show OPD record lifecycle status 2026-06-27 00:21:02 +05:30
c7c18adae2 Fix closure capture for M2 log mode flag 2026-06-26 23:58:00 +05:30
8c46a155ac M2 logs: remove misleading consent warning in local mode 2026-06-26 23:57:44 +05:30
ea3d88ce46 M2 local mode: treat consent-missing as pending info log 2026-06-26 23:54:31 +05:30
617cecdcbf Fix push_to_gateway variable scope in fhir submit flow 2026-06-26 23:49:51 +05:30
a797b7d096 Fix fhir_bundle_submit undefined push_to_gateway variable 2026-06-26 23:49:32 +05:30
d4595fa028 M2 flow: default OPD submit to HMS source care-context mode 2026-06-26 23:41:58 +05:30
51e5ab026c ABDM M2 compliance: strict EAtria auth/HFR and callback replay guards 2026-06-26 17:52:21 +05:30
ab564c77f8 ABDM OPD share: fix null-consent crash in care-context fallback 2026-06-26 16:46:10 +05:30
5d1d7ea552 ABDM OPD share: allow care-context push without active consent and log to bridge log 2026-06-26 16:43:19 +05:30
e7e5cf88e7 ABDM submit: release session lock before internal handoff and extend client timeout 2026-06-26 16:39:53 +05:30
a23d1f215a ABDM submit: prevent indefinite loading with fetch timeout and safer response handling 2026-06-26 16:35:36 +05:30
428dcd2aa9 ABDM: treat transient handoff timeout as queued when recent OPD record exists 2026-06-26 16:30:52 +05:30
fbaa985857 feat(abdm): implement M2 gateway contract endpoints and live test tooling 2026-06-24 04:50:03 +05:30
985d476bc1 ABDM: finalize ABHA verify persistence, M2 routes/workflows, and location masters seeding 2026-06-24 03:15:22 +05:30
75e71c2343 Fix new patient create 500 from undefined ABHA lock flag 2026-06-22 08:30:36 +05:30
386055a0cd fix(discharge): unify history panel behavior and form nav sync 2026-06-22 02:40:50 +05:30
a602bf555d feat(discharge): unify history sections into single risk profile panel 2026-06-22 02:07:49 +05:30
96c030b72d chore: checkpoint before discharge history panel refactor 2026-06-22 02:05:24 +05:30
8fc60e893e Fix pharmacy stock sync for invoice, purchase edit, challan and return flows 2026-06-20 11:25:40 +05:30
fe2fabc5b8 Make OPD placeholder headings consistently bold 2026-06-19 13:20:29 +05:30
b19d1d40c2 Fix OPD PDF overflow and compact consult placeholders 2026-06-19 13:12:34 +05:30
1bac1f6e04 feat: update storestock flow and ABDM bridge handling 2026-06-18 17:38:20 +05:30
1790be3fca ABDM M2: records push, discover/fetch, non-ABHA local storage, consent table compat
- EAtriaBridgeConnector: fix OPConsultRecord hi_type normalization (was wrongly
  mapping to PrescriptionRecord); allow push with either abha_address or abha_id;
  add careContextId alias for care_context_reference in pushRecord payload

- AbdmGateway: migrate OPD share to records/push semantics with unique
  care_context_reference, ABHA id/address resolution, bridge_record_id capture,
  and 409 DUPLICATE_RECORD non-fatal handling

- AbdmGateway: add non-ABHA local-only storage path for OPD/IPD/Lab share
  (push_status=local_only, no bridge call, audit logged)

- AbdmGateway: add POST /records/discover endpoint with ABHA-first + fallback
  matching by mobile, hospital ID, patient UHID+birthYear (PHR-compatible)

- AbdmGateway: add GET /records/fetch/{careContextId} endpoint returning
  decrypted FHIR payload from health_records

- AbdmGateway: dual-write consent artefacts to abdm_consent_records AND
  consents table when both present; getActiveConsentRecord falls back to
  consents table when abdm_consent_records is absent

- AbdmAuditService: write to audit_logs (generic schema) when present,
  fallback to abdm_audit_logs; field-aware insert supports both schemas

- Routes: register /records/discover and /records/fetch/(:any)

- Webhook signature validator: check EKA_WEBHOOK_SECRET then HMS_WEBHOOK_SECRET
  for gateway compatibility
2026-06-17 20:07:39 +05:30
cad5a477bf Sync OPD history flow and discharge UI refinements 2026-06-11 19:30:02 +05:30
eefda96dca Preserve investigation profile test master order 2026-06-11 19:22:09 +05:30
0c2e1385cb Refine IPD discharge summary layout 2026-06-11 11:53:39 +05:30
191c25de68 Refine discharge placeholders and status heading 2026-06-11 10:24:04 +05:30
c0f7e213e6 Discharge templates: add status heading token and refine placeholders 2026-06-11 09:57:04 +05:30
f2a7546a9d Simplify discharge summary placeholders - eliminate confusion
Changes:
- Rename main placeholder: DISCHARGE_SUMMARY → CLINICAL_SUMMARY (clearer name)
- Keep DISCHARGE_SUMMARY as legacy alias for backward compatibility
- Rename: DISCHARGE_ADVICE → FOLLOW_UP_INSTRUCTIONS (more descriptive)
- Remove: INSTRUCTION_REMARK (duplicate removed)
- Group placeholders by category in code with comments
- Create comprehensive reference guide: DISCHARGE_PLACEHOLDERS_REFERENCE.md

Benefits:
- Clear distinction between clinical summary and discharge instructions
- Organized placeholder groups (clinical, instructions, other)
- Easy migration guide for existing templates
- Complete documentation with examples
2026-06-11 08:18:43 +05:30
586d3bde46 Add HTML debug mode to discharge summary for troubleshooting
- Add ?html=1 parameter to show_discharge to output HTML directly
- Shows debug info: IPD ID, template name, content lengths
- Bypass PDF generation to see rendered HTML content
- Helps diagnose PHP/rendering errors before PDF conversion

Usage: /Ipd_discharge/show_discharge/1007168/1?html=1&tpl=3
2026-06-11 08:08:15 +05:30
35893e1a33 Fix discharge summary section extraction by keeping standard heading
- Restore "Discharge Summary" heading for template extraction to work
- Show status as strong text below heading (not as replacement)
- Include discharge summary HTML editor content (instruction_remark)
- Section extraction requires consistent heading names

Previous fix broke section extraction by changing heading text
2026-06-11 07:59:56 +05:30
c091b60168 Add discharge summary free-text content to PDF output
- Include ipd_discharge_instructions.comp_remark in discharge summary section
- Previously only showed status header, missing actual discharge narrative
- Reuse existing instructionRowForMeta query to avoid duplicate DB calls
- Apply renderRichText() to properly display HTML editor content

Fixes missing discharge summary text for IPD 1007168 and similar cases
2026-06-11 07:47:35 +05:30
3dc9fe1df6 Fix discharge summary not appearing in PDF after HTML editor conversion
- Enhanced normalizeRichText() to detect and preserve HTML from HTML editors
- Added renderRichText() helper to safely render HTML vs plain text content
- Updated 4 rendering locations (narrative sections, systemic exams, investigations)
- Backward compatible: plain textarea fields still work correctly
- Fixes issue where strip_tags() removed all HTML formatting from editor content

Resolves blank discharge summaries in PDF when content saved from TinyMCE/HTML editors
2026-06-11 07:38:40 +05:30
203481b8df Fix all patient_master_exten references in pharmacy module
- Replace all patient_master_exten checks with patient_master across Medical.php
- Fixes blank patient info in multiple pharmacy pages:
  * /Medical/ipd_print/{id}/credit - IPD print bills (UHID, Patient name)
  * Counter sale forms and invoice editing
  * Patient search functionality
  * IPD group print consolidated views
  * Auto UHID lookup endpoints
- patient_master_exten table exists but lacks core patient fields (p_fname, p_rname, p_code)
- Ensures consistent patient data display throughout pharmacy module
- Matches earlier fixes for billing and invoice list pages
2026-06-10 13:53:15 +05:30
1c87edcf03 Fix blank patient info in pharmacy invoice list
- Use patient_master directly in list_med_inv and list_med_orginv methods
- patient_master_exten exists but lacks p_fname, p_rname, p_code fields
- Fixes blank Name/Age/Gender/P Code in /Medical/list_med_inv page
- Consistent with earlier fix for list_org_ipd
2026-06-10 13:37:45 +05:30
0428c4d656 Fix blank patient names in pharmacy IPD list
- Use patient_master table directly instead of patient_master_exten
- patient_master_exten may exist but lacks p_fname, p_rname fields
- Matches pattern used in IpdBillingModel::baseIpdListQuery()
- Fixes blank patient names/codes in /Medical/list_org_ipd page
2026-06-10 13:24:35 +05:30
a4e6f69728 Fix IpdModel method call in toggleStatus endpoint
- Change getById() to find() - IpdBillingModel doesn't have getById method
- Use ipdEditModel (IpdModel extends Model) which has standard find() method
- Fixes 500 error: Call to undefined method IpdBillingModel::getById
2026-06-10 13:14:27 +05:30
54d120e2bb Fix IPD status toggle route registration
- Rename toggleIpdStatus() to updateDischargeToggleStatus() to match naming pattern
- Add route mapping for /billing/ipd/panel/{id}/discharge/toggle-status endpoint
- Fixes 404 error when clicking toggle button in discharge panel
- Follows same pattern as other discharge operations (discount, charge, update)
2026-06-10 13:10:03 +05:30
c437652b79 Add IPD status management with strict ipd_status check
- Update isIpdDischargedInvoice to check ONLY ipd_status field (remove fallback checks)
- Add IPD status toggle UI in discharge panel (Active/Discharged control)
- Create toggleIpdStatus controller method with permission check
- Add billing.ipd.status.manage permission for controlling bill edit lock
- Allows editing bills when needed by toggling status independently of discharge_date
- Auto-releases bed when setting status to discharged
2026-06-10 12:55:47 +05:30
bb95756700 Fix IPD Discharge medicine section: dose labels, Rx-Groups, and substitutes
- Fix dose columns showing IDs instead of labels (OD, BID, TDS, etc.)
- Add Rx-Group functionality with modal, search, and bulk add
- Add substitute medicine suggestions with one-click use
- Improve medicine autocomplete with debouncing and scope=all
- Load dose master maps in controller and pass to view
- Match OPD Consult UI/UX patterns for consistency
2026-06-09 17:23:34 +05:30
d722714ef1 feat: Complete bed management system with transfer and time tracking
- 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
2026-06-09 08:39:48 +05:30
8e293c4ffb Fix Chrome PDF corruption by clearing output buffers and adding X-Content-Type-Options header
- Clear all output buffers before sending PDF binary to prevent corruption
- Add X-Content-Type-Options: nosniff to force Chrome to treat response as PDF
- Apply fixes to main, fallback, and ultimate fallback PDF response paths
- Fixes issue where Chrome fails to open PDF while Firefox/Edge work
- Critical for PDFs with Hindi/UTF-8 content where output buffering can corrupt binary data
2026-06-08 23:30:12 +05:30
46315ac5ed Fix Chrome PDF display issue by adding Content-Length, proper filename encoding, Cache-Control, and Accept-Ranges headers 2026-06-08 23:20:06 +05:30
52f5041c5c Add dynamic margin system for letterhead printing - 5cm top, 2cm bottom when header hidden 2026-06-08 17:21:54 +05:30
0568851783 Add Print Header checkbox for IPD bill printing - allows printing on letterhead 2026-06-08 17:18:02 +05:30
f55d300924 Fix: SIGNATURE_BLOCK placeholder and cached content issue
ISSUE 1: {{SIGNATURE_BLOCK}} placeholder not working
- Signature extraction was using wrong end markers
- Start: 'Signature of Consultant'
- End: 'Signature of Medical Officer', 'Signature of Receiver / Date'
- Problem: All three texts are in SAME table row
- Extraction cut off too early (found end marker immediately after start)

FIX: Remove end markers for signature block extraction
- Signature table is LAST element in content
- Extract from 'Signature of Consultant' to end of content
- Now captures entire signature table correctly

ISSUE 2: Other Advice not showing in PDF
- Cached content was generated BEFORE 'Other Advice:' label was added
- Database has data but cached HTML doesn't include label

FIX: Created cache clearing utility
- clear_discharge_cache.php script
- Clears cached content for specified IPD
- Forces regeneration with new labels

DEBUG TOOLS ADDED:
- debug_discharge_content.php - Check what's in cached content
- clear_discharge_cache.php - Clear cache to force regeneration

TESTING:
1. php clear_discharge_cache.php 1
2. Visit /Ipd_discharge/preview_discharge_report/1?regen=1
3. Verify PDF shows Other Advice: and Discharge Summary: labels
4. Verify {{SIGNATURE_BLOCK}} placeholder works in templates
2026-06-07 20:12:58 +05:30
5f052945d2 Fix: Add Discharge Summary label and separate placeholders for instruction fields
ISSUE 1: Discharge Summary showing in PDF but without label
ISSUE 2: Need separate placeholders for Other Advice and Discharge Summary

FIX 1: Added label to instruction_remark in PDF
- Added Discharge Summary: label before instruction_remark content

FIX 2: Added new placeholders for template flexibility
- OTHER_ADVICE - Shows only Other Advice field
- INSTRUCTION_REMARK or DISCHARGE_ADVICE - Shows only Discharge Summary field
- DISCHARGE_INSTRUCTIONS - Shows full section with all advice

Now templates can control what appears where using specific placeholders.

CHANGES:
1. Line 2248 - Added Discharge Summary: label
2. Line 574-575 - Extract new tokens from content
3. Line 579-581 - Add tokens to vars array
4. Line 520-522 - Add markers to extraction list

TESTING: Go to discharge PDF and verify labels show correctly
2026-06-07 20:07:34 +05:30
2b95bb8b7c Fix: Data mixing between instruction_other and instruction_remark fields
ISSUE: instruction_remark (Discharge Summary) data appearing in instruction_other (Other Advice) field after save

ROOT CAUSE: Legacy table sync was writing wrong variable
- Save handler at line 5478 was writing \ to legacy food_text
- Should have been writing \
- When legacy fallback loads (if food_ids empty), wrong data copied to instruction_other

FIX: Changed line 5478 in Ipd_discharge.php
- Before: \['food_text'] = \;
- After:  \['food_text'] = \;

FILES MODIFIED:
1. app/Controllers/Ipd_discharge.php - Fixed legacy save handler
2. app/Views/billing/ipd/discharge_create.php - Removed debug comments

TESTING STEPS:
1. Clear corrupt legacy data: php clear_legacy_food.php 1
2. Go to /Ipd_discharge/ipd_select/1
3. Clear both fields
4. Type 'Hello Other' in Other Advice
5. Type 'Hello Discharge' in Discharge Summary
6. Click 'Save Discharge Advice'
7. After reload: Other Advice should show 'Hello Other', NOT 'Hello Discharge'

SCRIPTS ADDED:
- check_instruction_db.php - Check database values
- check_legacy_food.php - Check legacy table
- clear_legacy_food.php - Clean corrupt legacy data
- list_instruction_records.php - List all records
2026-06-07 20:00:59 +05:30
69373af48c Fix: Add CKEditor special character sanitization for PDF generation
Added sanitizeCKEditorSpecialChars() method to handle smart quotes, zero-width spaces, em/en dashes, and other special characters that can break mPDF.

Removes invisible Unicode chars, replaces special punctuation with ASCII equivalents, cleans HTML comments.
2026-06-07 13:53:03 +05:30
328de6279d Fix: Disable auto-generation of discharge templates + add manual creation button
ISSUE: Templates auto-regenerate when deleted
User deletes template ID 3, page reload creates template ID 4 automatically

ROOT CAUSE: ensureDefaultDischargeTemplateSeeded() called on EVERY page load
- discharge_templates() method called it on every view
- getDischargeTemplateRows() called it on every discharge PDF generation
- When count=0, it auto-inserted default templates
- Made it impossible to delete all templates

SOLUTION: Changed to manual opt-in template creation

1. Removed auto-seeding calls:
   - Setting/Template::discharge_templates() - removed ensureDefaultDischargeTemplateSeeded()
   - Ipd_discharge::getDischargeTemplateRows() - removed ensureDefaultDischargeTemplateSeeded()
   - Both now only call ensureDischargeTemplateTable() (structure check only)

2. Added manual template creation:
   - New 'Create Default Templates' button shown when table is empty
   - New endpoint: discharge_templates_seed() - creates defaults on demand
   - Route: POST /setting/template/discharge_templates_seed
   - Button confirms before creating, shows success message, reloads page

3. Preserved seeding functions:
   - ensureDefaultDischargeTemplateSeeded() kept but not auto-called
   - Can be manually triggered via new button
   - Creates 'Default Discharge Template' and 'NABH Compliant Discharge Summary'

BEHAVIOR NOW:
- Users can delete ALL templates - they stay deleted
- Empty table shows helpful message with creation button
- Templates only created when user explicitly requests them
- No more surprise template regeneration

TESTING:
- Delete all templates
- Page reloads showing empty table with button
- Click 'Create Default Templates'
- 2 templates created (ID 1 and 2)
2026-06-07 11:38:18 +05:30
d923dc6c29 Fix: Template delete page refresh + add debug logging
ISSUE: Template delete returns success but record appears not deleted

ROOT CAUSE: Delete WAS working (verified in database), but page wasn't refreshing properly after success

CHANGES:

1. JavaScript fix (discharge_templates.php):
   - Replaced conditional load_form_div / location.assign logic
   - Now uses simple location.reload() after 500ms delay
   - Ensures page always refreshes after successful delete

2. Controller debug logging (Template.php):
   - Added comprehensive debug logs to trace delete flow
   - Logs: request ID, row fetch, query compilation, affected rows
   - Logs error codes and messages for troubleshooting
   - Will help diagnose future issues

VERIFIED:
- Database confirmed template ID 2 was deleted
- Only frontend refresh was failing
- Now forces reload to show updated list
2026-06-07 11:32:24 +05:30
ea07063675 Fix: Prevent duplicate medicine saves on 'Save Discharge Advice' button
ISSUE: Medicines were being saved twice - once via Add button AJAX, and again when clicking 'Save Discharge Advice' button.

ROOT CAUSE:
1. Legacy code in save_main handler (lines 5489-5538) read 'discharge_medicine_json' POST field
2. JavaScript serializeDischargeMedicineTable() collected all medicine table rows into JSON
3. On form submit (Save Discharge Advice), JSON was sent and controller re-inserted all medicines
4. Result: duplicate entries in ipd_discharge_prescrption_prescribed table

SOLUTION:
- DISABLED controller code that processes discharge_medicine_json in save_main handler
- DISABLED JavaScript call to serializeDischargeMedicineTable() on form submit
- Medicines now saved ONLY via Add button AJAX (action='add_drug')
- Save Discharge Advice button now only saves dietary advice, instructions, review after, etc.

TESTING:
1. Add medicines via Add button (saves immediately)
2. Click Save Discharge Advice (does NOT save medicines again)
3. No duplicate entries in database
2026-06-07 09:03:12 +05:30
783ddcbacc Fix discharge medications: add Dosage column with English+Hindi labels
- Add getDoseMasterRows() to load dose masters (opd_dose_shed, opd_dose_when, opd_dose_frequency)
- Add buildDosageDisplay() to format dosage: 'BID (TWO TIME A DAY) / दिन में दो बार लेना'
- Update buildAutoDischargeContent() medication table query to include dosage, dosage_when, dosage_freq fields
- Change table columns from '#|Medicine|Qty|Days|Notes' to 'Medicine Name|Dosage|Qty|Day' matching old CI3 format
- Dosage column shows full text labels from master tables, not numeric IDs
- Add composition support as small text under medicine name for legacy compatibility
- Remove # serial number column and Notes column to match old HMS format
2026-06-07 08:43:45 +05:30
89c150324f Add refresh parameter to force regenerate cached discharge content in PDF
Problem:
- PDF shows old cached content with 'Date of Discharge: 2026-06-05'
- Debug page shows correct new format (status header only)
- Discharge content is cached in ipd_discharge table
- PDF generation uses cached content from database
- Fix only affects newly generated content, not cached content

Root Cause:
When discharge is first created, content is generated and saved to DB.
PDF generation flow (show_discharge method):
1. Load cached content from ipd_discharge table
2. Only regenerate if content is empty
3. Apply template and render PDF

So old discharges still have old format cached.

Solution:
Added 'refresh' parameter to show_discharge() method:
- If refresh=1, ignore cached content and regenerate
- Regenerate using buildAutoDischargeContent() (has fix)
- Save new content to database
- Then render PDF

Code Change (line 5900-5913):
Added:
  \ = (int) (\->request->getGet('refresh') ?? 0) === 1;

Changed:
  if (\ || trim(strip_tags(\)) === '') {

Usage:
1. Original URL (uses cache):
   http://localhost:8080/Ipd_discharge/show_discharge/1/1?tpl=1

2. Force refresh (regenerates):
   http://localhost:8080/Ipd_discharge/show_discharge/1/1?tpl=1&refresh=1

3. After first refresh, cache is updated with new format
   Subsequent views will use new cached content

Note:
- preview_discharge_report() already has 'regen=1' parameter
- Same functionality, different parameter name
- Both methods now support force regeneration

For existing discharges:
- Add &refresh=1 to URL once to update cache
- Or recreate discharge from edit page
- Or clear ipd_discharge.content for that IPD ID"
2026-06-07 08:24:38 +05:30
d096585df6 \Fix {{DISCHARGE_SUMMARY}} placeholder - remove extra information
Problem:
- {{DISCHARGE_SUMMARY}} placeholder was showing:
  1. Discharge status header (Discharge Summary/LAMA/etc.)
  2. Department information
  3. Treating Doctor(s) information
  4. Date of Admission
- User wants ONLY the status header in this placeholder
- Extra information should be removed from {{DISCHARGE_SUMMARY}}

Solution:
Modified buildAutoDischargeContent() method:

Before (lines 1679-1703):
- Built dischargeSummaryParts array with department/doctor/date
- Added all info in one section with header + div containing details

After:
- {{DISCHARGE_SUMMARY}} now contains ONLY the status header
- Removed department, doctor, and admission date from this section
- Status header comes from ipd_discharg_status table via:
  ipd_master.ipd_status (or discarge_patient_status) = ipd_discharg_status.id
  Returns ipd_discharg_status.status_details field

Status Values:
- ipd_status = 0 → 'Discharge Summary' (hardcoded)
- ipd_status = 1 → From DB: 'Discharge Summary'
- ipd_status = 2 → From DB: 'Leave Against Medical Advice'
- ipd_status = 3 → From DB: 'Refer To Higher Centre'
- ipd_status = 5 → From DB: 'Dead Summary'
- ipd_status = 7 → From DB: 'Discharge on Request'

Now {{DISCHARGE_SUMMARY}} outputs:
<h4 class='discharge-section-heading'>Discharge Summary</h4>
OR
<h4 class='discharge-section-heading'>Leave Against Medical Advice</h4>

That's it - no extra lines below.

If user needs department/doctor/date info, they can use individual tokens:
- {{DEPARTMENT}}
- {{DOCTOR_NAMES}}
- {{ADMIT_DATE_ONLY}}
- {{DISCHARGE_DATE_ONLY}}
- {{ADMISSION_TIME}}
- {{DISCHARGE_TIME}}

Or use {{PATIENT_INFO_TABLE}} which has all patient demographics.

Testing:
- Visit: /Ipd_discharge/debug_discharge_html/1
- Check {{DISCHARGE_SUMMARY}} section
- Should only show status header, no other info"
2026-06-07 08:12:03 +05:30
751fdfaedb Remove all inline styles and use semantic CSS classes
Problem:
- Inline styles in HTML override custom CSS defined in templates
- User's custom styles (font-family, table borders, padding) not applied
- Hard to maintain and customize styling
- Inline styles have higher specificity than class/ID selectors

Solution:
Replaced all inline styles with semantic CSS classes:

Section Headings:
- style='margin:16px 0 8px 0' → class='discharge-section-heading' (h4)
- style='text-align:center;margin:...' → class='discharge-title' (h2)

Lists:
- style='margin:0 0 10px 20px' → class='discharge-list' (ul/ol)
- style='margin:4px 0 8px 20px' → class='discharge-sublist' (ul)
- style='list-style:none' → class='no-bullet' (li)

Text:
- style='color:#475569' → class='discharge-remark' (span)

Tables:
- style='width:100%;border-collapse:...' → class='discharge-table'
- Medicine table → class='discharge-medicine-table'
- Patient info → class='discharge-info-table'
- Signature block → class='discharge-signature-table'
- Removed all inline width/align styles from th/td

Containers:
- style='margin-bottom:8px' → class='discharge-field'
- style='margin-top:6px' → class='discharge-footer'
- style='margin-bottom:6px' → class='discharge-item'
- Added class='discharge-section' for section wrappers

Separators:
- style='margin:1px;padding:0' → class='discharge-separator' (hr)

Changes Made:
1. app/Controllers/Ipd_discharge.php:
   - buildAutoDischargeContent() - All section builders
   - buildAutoDischargeSummaryTable() - Patient info table
   - addListSection() - List sections
   - buildNursingTrendSection() - Nursing trends
   - defaultDischargeTemplateHtml() - Default template
   - nabhDischargeTemplateHtml() - NABH template

2. Created DISCHARGE_CSS_CLASSES.md:
   - Complete CSS class reference
   - Suggested stylesheet with all classes
   - Customization guide
   - Example usage
   - Print optimization styles

Benefits:
✓ User's custom CSS now applies correctly
✓ No style conflicts or overrides
✓ Easy to customize via CSS
✓ Consistent styling across all sections
✓ Maintainable - change CSS once, applies everywhere
✓ Print-friendly with @media print rules

Usage:
1. Copy CSS from DISCHARGE_CSS_CLASSES.md
2. Add to discharge template 'template_css' field
3. Or add to global print CSS
4. Customize colors/spacing/fonts as needed

The existing body/table/td/p styles will now work properly
No inline styles to override custom CSS anymore
2026-06-07 07:56:11 +05:30
3c430fa386 Fix discharge status header in auto-generated content and remove Date of Discharge
CRITICAL FIX - User Requirement:
- If ipd_status = 0: Show 'Discharge Summary' only
- If ipd_status != 0: Show value from ipd_discharge_status.status_details
- Remove 'Date of Discharge' line completely

Problem:
- {{DISCHARGE_SUMMARY}} still showed 'Discharge Summary' header regardless of status
- 'Date of Discharge: YYYY-MM-DD' line was appearing
- Previous fix only worked on saved content via regex, not on auto-generated content

Root Cause:
- buildAutoDischargeContent() method had hardcoded 'Discharge Summary' header
- getDischargeStatusText() was querying database but header wasn't being used
- Date of Discharge was being added to dischargeSummaryParts array

Solution:

1. Updated buildAutoDischargeContent() method (line ~1670):
   - Removed 'Date of Discharge' from dischargeSummaryParts array
   - Added comment: 'NOTE: Date of Discharge removed per user request'
   - Call getDischargeStatusText() to get dynamic header
   - Use status-based header instead of hardcoded 'Discharge Summary'
   - Now generates: <h4>status_details_value</h4> instead of <h4>Discharge Summary</h4>

2. Updated getDischargeStatusText() method (line ~1047):
   - Added early return for ipd_status = 0: returns 'Discharge Summary'
   - For ipd_status != 0: queries ipd_discharge_status table
   - Returns status_details field (primary)
   - Falls back to status_desc if status_details is empty
   - Final fallback: 'Discharge Summary'

3. Updated buildAutoDischargeSummaryTable() method (line ~1517):
   - Used for {{PATIENT_INFO_TABLE}} token
   - Now uses getDischargeStatusText() for header
   - Changes <h2>Discharge Summary</h2> to <h2>status_value</h2>
   - Keeps patient info table structure unchanged

Status Mapping Logic:
- ipd_status = 0 → 'Discharge Summary' (special case, no DB lookup)
- ipd_status = 1 → Query DB → 'Discharge Summary' (from status_details)
- ipd_status = 2 → Query DB → 'Leave Against Medical Advice'
- ipd_status = 3 → Query DB → 'Refer To Higher Centre'
- ipd_status = 5 → Query DB → 'Dead Summary'
- ipd_status = 7 → Query DB → 'Discharge on Request'

Content Structure Before:
<h4>Discharge Summary</h4>
<div>
<b>Department:</b> General Surgery<br>
<b>Treating Doctor(s):</b> Dr. Name<br>
<b>Date of Admission:</b> 04-06-2026<br>
<b>Date of Discharge:</b> 07-06-2026
</div>

Content Structure After:
<h4>Leave Against Medical Advice</h4>
<div>
<b>Department:</b> General Surgery<br>
<b>Treating Doctor(s):</b> Dr. Name<br>
<b>Date of Admission:</b> 04-06-2026
</div>

Testing:
1. Set ipd_master.ipd_status = 0 → regenerate → should show 'Discharge Summary'
2. Set ipd_master.ipd_status = 1 → regenerate → should show 'Discharge Summary'
3. Set ipd_master.ipd_status = 2 → regenerate → should show 'Leave Against Medical Advice'
4. Set ipd_master.ipd_status = 5 → regenerate → should show 'Dead Summary'
5. 'Date of Discharge' line should NOT appear in any case

Files Modified:
- app/Controllers/Ipd_discharge.php:
  - getDischargeStatusText() - Added ipd_status = 0 check
  - buildAutoDischargeContent() - Removed Date of Discharge, use dynamic header
  - buildAutoDischargeSummaryTable() - Use dynamic header

IMPORTANT: User must REGENERATE discharge summary after pulling code
- Click 'Regenerate' button on discharge preview page
- Or delete existing discharge content and reload form
- Old saved content will still have old header until regenerated
2026-06-07 07:42:38 +05:30
09570e0793 Make discharge summary header dynamic based on discharge status
Problem:
- {{DISCHARGE_SUMMARY}} always showed 'Discharge Summary' header
- User wants header to change based on patient discharge status
- 'Date of Discharge' line was unwanted
- Need to see HTML source to check spacing between placeholders

Solution:

1. Added getDischargeStatusText() method:
   - Queries ipd_discharge_status table
   - Uses ipd_master.ipd_status as lookup key
   - Returns status_details or status_desc from table
   - Fallback: 'Discharge Summary' if status not found

2. Modified buildDischargeSectionTokenVars():
   - Now accepts panelData parameter (has ipd info)
   - Gets discharge status text via getDischargeStatusText()
   - Replaces 'Discharge Summary' heading with status text
   - Removes 'Date of Discharge: YYYY-MM-DD' line
   - Uses regex to handle multiple HTML tag formats (h1-h6, b, strong, p)

3. Added debug_discharge_html() endpoint:
   - URL: /Ipd_discharge/debug_discharge_html/{ipdId}
   - Shows complete HTML source with syntax highlighting
   - Displays rendered template with all placeholders replaced
   - Useful for checking spacing and HTML structure
   - Auto-generates content if not saved yet

Database Schema:
- ipd_master.ipd_status: 0-7 (discharge status ID)
- ipd_discharge_status table:
  - id: 0-7
  - status_desc: 'Status Pending', 'Improved/Recovered', 'LAMA', 'Referred', etc.
  - status_details: 'Discharge Summary', 'Leave Against Medical Advice', etc.

Status Mapping (from user's data):
- 0: Status Pending
- 1: Improved/Recovered -> 'Discharge Summary'
- 2: LAMA -> 'Leave Against Medical Advice'
- 3: Referred -> 'Refer To Higher Centre'
- 4: Satisfactory -> 'Discharge Summary'
- 5: Expired -> 'Dead Summary'
- 6: Admission Cancelled
- 7: Discharge on Request

Regex Replacements:
1. Header replacement: /<h[1-6][^>]*>\s*Discharge\s+Summary\s*<\/h[1-6]>/i
2. Bold replacement: /<(b|strong)>\s*Discharge\s+Summary\s*<\/\1>/i
3. Date removal (br): /Date\s+of\s+Discharge\s*:\s*[0-9\-\/]+\s*<br\s*\/?>/i
4. Date removal (p): /<p[^>]*>\s*Date\s+of\s+Discharge\s*:\s*[0-9\-\/]+\s*<\/p>/i

Usage:
- When ipd_status = 1: Shows 'Discharge Summary' (from status_details)
- When ipd_status = 2: Shows 'Leave Against Medical Advice'
- When ipd_status = 5: Shows 'Dead Summary'
- 'Date of Discharge: 2026-06-07' line is removed from all sections

Debug Endpoints:
1. /Ipd_discharge/debug_ipd_fields/{ipdId} - Shows database field values
2. /Ipd_discharge/debug_discharge_html/{ipdId} - Shows complete HTML source

Testing:
- Change ipd_master.ipd_status value
- Regenerate discharge summary
- Header should change based on status
- Date line should not appear
- Use debug_discharge_html to see full HTML structure
2026-06-07 07:35:36 +05:30
e152fab496 Fix discharge time placeholders and department/doctor field mappings
CRITICAL FIXES based on actual database schema analysis:

Problem 1: {{ADMISSION_TIME}} showing 12:00 AM
- Code was looking for: register_time, admission_time (don't exist)
- Actual field: reg_time (stores '14:44' format)
- Fix: Changed to use ipd->reg_time field

Problem 2: {{DISCHARGE_TIME}} showing 12:00 AM
- Code was looking for: discharge_date datetime field
- Actual field: discharge_time (stores '05:30' format)
- Fix: Changed to use ipd->discharge_time field directly

Problem 3: {{DEPARTMENT}} showing blank
- Code was using: hc_department.id field for lookup
- Actual field: hc_department.iId (primary key is iId, not id)
- Fix: Changed WHERE clause from 'id' to 'iId'

Problem 4: {{DOCTOR_NAMES}} showing blank
- Code was looking for: doc_list, doctor_id, doc_id (don't exist)
- Actual field: r_doc_id (referring doctor ID = 12)
- Fix: Changed primary lookup to r_doc_id field

Technical Improvements:

1. Enhanced safeTime() function:
   - Added regex parsing for 'HH:MM' time format
   - Validates hour (0-23) and minute (0-59) ranges
   - Converts 24-hour to 12-hour format with AM/PM
   - Example: '14:44' -> '02:44 PM', '05:30' -> '05:30 AM'
   - Falls back to strtotime() for datetime formats
   - Returns empty string for invalid times

2. Updated getDischargeDoctorNames():
   - Primary: ipd->r_doc_id (referring doctor)
   - Fallback: ipd->doc_list (comma-separated IDs)
   - Fallback: ipd->doctor_id, doc_id, consultant_id
   - Queries doctor_master table
   - Gets specializations from doc_spec + med_spec
   - Format: 'Dr. Name [Specialization]' or 'Title Name [Spec]'

3. Updated getDischargeDepartmentName():
   - Changed: WHERE id = dept_id
   - To: WHERE iId = dept_id
   - Keeps fallback to ipd_department table
   - Returns department vName field

4. Updated debug endpoint:
   - Now checks: reg_time, reg_time_bak, discharge_time, discharge_time_bak
   - Shows: dept_id, r_doc_id, r_doc_name
   - Removed non-existent fields from output

Database Schema (from live data):
- ipd_master.reg_time: '14:44' (admission time)
- ipd_master.discharge_time: '05:30' (discharge time)
- ipd_master.dept_id: 2 -> hc_department.iId (vName field)
- ipd_master.r_doc_id: 12 -> doctor_master.id (p_fname field)

Testing:
- Admission Time should show: 02:44 PM (from reg_time '14:44')
- Discharge Time should show: 05:30 AM (from discharge_time '05:30')
- Department should show department name from hc_department
- Doctor Names should show doctor name with specialization
2026-06-07 07:07:35 +05:30
87789cff7a Add debug endpoint to check IPD master fields
Problem:
- {{ADMISSION_TIME}} showing 12:00 AM instead of actual time
- {{DISCHARGE_TIME}} showing 12:00 AM instead of actual time
- {{DEPARTMENT}} showing blank
- {{DOCTOR_NAMES}} showing blank

Need to identify:
1. Which datetime fields exist in ipd_master table
2. Which department field exists (dept_id, department_id, or department)
3. Which doctor field exists (doc_list, doctor_id, doc_id, consultant_id)
4. What values are actually stored in these fields

Debug Endpoint Added:
- URL: /Ipd_discharge/debug_ipd_fields/{ipdId}
- Example: http://localhost:8080/Ipd_discharge/debug_ipd_fields/123
- Replace 123 with actual IPD ID from your discharge page

What it shows:
- All available field names in ipd_master table
- Values of: register_date, discharge_date, register_time, discharge_time, admission_time
- Values of: dept_id, department_id, department
- Values of: doc_list, doctor_id, doc_id, consultant_id
- Result of getDischargeDepartmentName() function
- Result of getDischargeDoctorNames() function
- Result of safeTime() for register_date and discharge_date

Usage:
1. Go to your discharge form
2. Note the IPD ID from the URL
3. Open: /Ipd_discharge/debug_ipd_fields/{ipdId} in browser
4. Check the JSON output to see which fields exist and their values

This will help identify:
- If datetime fields have time component or just date
- Which field names are actually used in your database
- Why placeholders are showing blank/wrong values
2026-06-07 06:58:59 +05:30
51aa6400c8 Fix {{DEPARTMENT}} and {{DOCTOR_NAMES}} placeholder tokens
Problem:
- {{DEPARTMENT}} and {{DOCTOR_NAMES}} placeholders not working in discharge templates
- Complex GROUP_CONCAT query with LEFT JOINs causing issues
- Query might return NULL or fail silently when specializations missing

Solution - getDischargeDoctorNames():
- Removed GROUP_CONCAT to avoid SQL aggregation issues
- Split into two separate queries: doctors first, then specializations
- Changed specialization JOIN from LEFT to INNER to avoid NULL values
- Query doctors from doctor_master separately
- For each doctor, query doc_spec + med_spec to get specializations
- Build full name format: 'Dr. Name [Spec1, Spec2]' or 'Title Name [Spec1, Spec2]'
- Return comma-separated list of all doctors

Technical Changes:
- First query: SELECT d.id, d.p_fname, d.p_title FROM doctor_master
- Second query (per doctor): SELECT m.SpecName FROM doc_spec s JOIN med_spec m
- Use INNER JOIN for specializations to only include valid matches
- Handle missing specializations gracefully (show doctor name without brackets)
- Handle missing title (default to 'Dr.')

getDischargeDepartmentName() - Already Working:
- Tries dept_id from ipd_master
- Queries hc_department table first
- Falls back to ipd_department table
- Falls back to direct department field
- Returns empty string if all methods fail

Token Flow:
1. buildDischargeSummaryTokenVars() calls both functions
2. Returns array with 'DEPARTMENT' and 'DOCTOR_NAMES' keys
3. buildDischargeTemplateTokenVars() merges these tokens
4. Creates lowercase, UPPERCASE, and Ucfirst versions of all tokens
5. applyDischargeTemplateTokens() replaces {{TOKEN}} and {TOKEN} in template

Available Token Variants:
- {{DEPARTMENT}}, {{department}}, {{Department}}
- {{DOCTOR_NAMES}}, {{doctor_names}}, {{Doctor_names}}
- {{DOCTOR_NAME}} (singular alias for same value)

Example Output:
- Single doctor: 'Dr. John Smith [Cardiology]'
- Multiple doctors: 'Dr. John Smith [Cardiology], Dr. Jane Doe [Neurology]'
- No specialization: 'Dr. John Smith'
- With title: 'Prof. John Smith [Cardiology]'

Testing:
- Ensure doc_list field in ipd_master has comma-separated doctor IDs
- Falls back to doctor_id, doc_id, or consultant_id if doc_list empty
- Returns empty string if no valid doctor IDs found
2026-06-07 06:48:58 +05:30
e731ef61e9 Fix discharge medicine save, add CKEditor, and Review After quick select
Medicine Saving Fix (MAJOR):
- Add hidden field 'discharge_medicine_json' to capture medicine table data
- Add serializeDischargeMedicineTable() function to convert DOM table to JSON before form submit
- Hook serialization into form submit event (before syncEditorValues)
- Update controller to process discharge_medicine_json in save_main action
- Insert medicines into ipd_discharge_prescrption_prescribed or ipd_discharge_prescription_prescribed table
- Medicine data now persists on page reload

CKEditor Integration:
- Initialize CKEditor for 'instruction_other' (Other Advice) field
- Initialize CKEditor for 'instruction_remark' (Discharge Summary) field
- Add simplified toolbar: Bold, Italic, Underline, Lists, Undo/Redo
- Properly destroy existing instances before re-initialization
- Height: 120px for Other Advice, 150px for Discharge Summary

Review After Quick Select Buttons:
- Add getNextVisitOptions() method to Ipd_discharge controller (copied from Opd_prescription)
- Add resolveFirstField() helper method
- Pass next_visit_options array to view
- Render quick select buttons: '3 Days (09-06-2026)', '1 Week (13-06-2026)', etc.
- Add JavaScript handler: click button → populate #discharge_review_after input
- Change Review After field from col-md-4 to col-md-6 for better layout
- Add col-md-12 wrapper for button row with flex-wrap gap-2 layout

Technical Details:
- Medicine JSON structure: {med_type, med_name, dosage, dosage_when, dosage_freq, no_of_days, qty, remark}
- JSON processing includes column existence checks for flexibility
- Quick select buttons use data-value attribute for value insertion
- Falls back to hardcoded date options if opd_nextvisit table missing
- Medicine insert uses med_id=0 to mark client-added medicines

User Workflow:
1. Add medicines → shown in table (Type, Medicine, Dose labels, Duration formatted)
2. Click 'Save Discharge Advice' → medicines serialize to JSON → POST to controller
3. Controller parses JSON → inserts to database → medicines persist on reload
4. Other Advice/Discharge Summary now have rich text editing (bold, lists, etc.)
5. Review After: click '1 Week (13-06-2026)' button → auto-fills input
2026-06-06 20:53:05 +05:30
0d9ff81a97 Add DataTables search box support to patient search - now handles both initial search and live filtering 2026-06-06 14:56:02 +05:30
d82078c9ed Convert patient search to DataTables with AJAX server-side processing
- Updated Patient::search() to only render view with search query
- Created Patient::search_ajax() method for DataTables AJAX endpoint
- Implemented server-side processing with pagination, sorting, and filtering
- Results ordered by Last Visit DESC by default
- Retrieves all patient data from patient_master table
- Added proper SQL escaping to prevent injection
- Updated Patient_Search_V.php to use DataTables with AJAX remote data
- Added DataTables configuration with 25 rows per page default
- Supports dynamic length menu (10, 25, 50, 100, All)
- Added route for billing/patient/search_ajax endpoint
- Improved user experience with loading spinner and customized messages
2026-06-06 14:52:10 +05:30
550e72eca8 Add IPD Discharge search functionality with AJAX
- Added 'Discharge' button in sidebar under In-Patient & Nursing Care section
- Created search_patient() and search_patient_ajax() controller methods
- Implemented AJAX-based patient search by IPD Code, UHID, Name, or Mobile
- Added ipd_discharge/search_patient.php view with dynamic results table
- Search results show patient details, bed info, doctor assignments, and discharge status
- Added 'Create Discharge' and 'Print Discharge' action buttons for each patient
- Integrated DataTables for sorting and pagination
- Fixed database column names (patient_master.gender, age, age_in_month)
- Added routes for search page and AJAX endpoint
2026-06-06 14:43:10 +05:30
16348d12db Fix placeholder tokens: DISCHARGE_SUMMARY, DOCTOR_NAMES, DEPARTMENT
- Add 'Discharge Summary' section to buildAutoDischargeContent with department, doctors, and dates so {{DISCHARGE_SUMMARY}} token extracts properly
- Improve getDischargeDepartmentName to support dept_id, department_id fields and check both hc_department and ipd_department tables
- Improve getDischargeDoctorNames to fallback to doctor_id, doc_id, consultant_id if doc_list is empty
- Update DISCHARGE_TEMPLATE_TOKENS.md to clarify what {{DISCHARGE_SUMMARY}} contains
- Clear cached content for IPD 1 to regenerate with new logic

Fixes issue where {{DISCHARGE_SUMMARY}}, {{DOCTOR_NAMES}}, {{DEPARTMENT}} tokens were not working (replaced with empty values)
2026-06-06 13:00:52 +05:30
3ad0025c24 Add new discharge template tokens: PATIENT_PHONE, INSURANCE_COMPANY, DOCTOR_NAMES
New placeholders added:

1. PATIENT_PHONE - Patient's phone number from patient_master.mphone1 or ipd_master.P_mobile1
   Example: 9876543210

2. INSURANCE_COMPANY - Insurance company name from ipd_master.ins_short_name or ins_company_name
   Example: Star Health Insurance
   Default: 'Direct' if no insurance

3. DOCTOR_NAMES / DOCTOR_NAME - Comma-separated list of treating doctors with specialties
   Example: Dr. Rajesh Kumar [General Medicine], Dr. Priya Sharma [Cardiology]
   Reads from ipd_master.doc_list field and joins with doctor_master and med_spec tables

Changes:
- Added getDischargeDoctorNames() helper function
- Updated buildDischargeSummaryTokenVars() to include three new tokens
- Updated DISCHARGE_TEMPLATE_GUIDE.md with new token documentation
- Added example template showing usage of new tokens
- Updated CI3 to CI4 migration mapping table

These tokens match the data shown in the auto-generated patient summary table
and allow templates to display this information in custom layouts.
2026-06-06 12:21:37 +05:30
6d72a5ec04 Correct fix: Remove patient table from auto-generated content, add as token
OLD CI3 BEHAVIOR (correct):
- Patient demographic table was IN the template file
- Content variables contained ONLY clinical sections
- Template controlled entire layout

NEW CI4 FIX (matching CI3):
- Patient table removed from buildAutoDischargeContent completely
- Added {{PATIENT_INFO_TABLE}} token for templates to use if needed
- Auto-generated content now contains ONLY clinical sections
- Blank template = blank output (no patient table forced)
- Templates can add patient table using token or individual tokens

Changes:
- Removed includeSummaryTable parameter from buildAutoDischargeContent
- Removed templateHasDemographicTokens helper (no longer needed)
- Added PATIENT_INFO_TABLE token in buildDischargeTemplateTokenVars
- Simplified show_discharge and preview_discharge_report (no template detection)
- Added comment explaining CI3 compatibility

This matches the old CI3 chamunda_discharge_template_html.php pattern where:
- Template had hardcoded patient table structure
- Variables like \, \ were injected
- Content did NOT include patient demographics by default
2026-06-06 12:09:57 +05:30
224ac5613c Fix: Skip auto-generated patient info table when template has demographic tokens
- Modified buildAutoDischargeContent to accept includeSummaryTable parameter
- Added templateHasDemographicTokens helper to detect if template has patient info tokens
- Updated show_discharge and preview_discharge_report to check template before auto-generation
- When template has {{PATIENT_NAME}}, {{UHID}}, etc., skip auto-summary table
- Added clear_discharge_content.php script to clear cached content for regeneration
- Solves issue where blank templates still showed patient information table
2026-06-06 11:49:52 +05:30
aa812354a6 Change mPDF default font from thin dejavusans to medium-weight freeserif for better Hindi/Devanagari rendering
- Updated all controllers: Opd, Diagnosis, Billing\Charges, Billing\Ipd, Storestock, AbdmGateway
- freeserif provides better Unicode coverage and more readable font weight
- Ipd_discharge and DoctorDocument already used good fonts (freeserif/freesans)
- Added comprehensive font configuration documentation
2026-06-06 11:19:35 +05:30
38e06ed1d7 Add 'Save in Master' quick-add for Course/Treatment section
FEATURE: Quick-add functionality for Course/Treatment master terms

NEW COMPONENTS:
1. Course master table: ipd_discharge_course_master
   - term_name, term_code, icd_code, is_active
   - Auto-creates on first use
2. Controller endpoints in Ipd_discharge.php:
   - course_master_lookup() - AJAX autocomplete search
   - course_master_list() - Full list with filters
   - course_master_save() - Create/update records
   - course_master_delete() - Remove records
3. Routes added to Config/Routes.php:
   - Ipd_discharge/course_master_lookup (GET)
   - Ipd_discharge/course_master_list (GET)
   - Ipd_discharge/course_master_save (POST)
   - Ipd_discharge/course_master_delete (POST)

VIEW CHANGES (discharge_create.php):
- Course input now uses input-group layout
- Green 'Save in Master' button added
- Custom dropdown for autocomplete with code badges
- Hidden field: new_course_master_id
- JavaScript: initCourseAutocomplete() function
- Integrated with existing quickAddTermModal

QUICK-ADD MODAL ENHANCEMENT:
- Now supports 3 types: surgery, procedure, course
- Dynamic endpoint selection based on type
- Course type uses course_master_save endpoint
- Auto-populates course input and master_id on save

AUTOCOMPLETE FEATURES:
- Type 2+ characters → searches course_master table
- Dropdown shows: Name + SNOMED/ICD code badges
- Arrow key navigation (Up/Down/Enter/Escape)
- Click or Enter to select
- Hover highlighting with visual feedback
- 300ms debounce for performance

WORKFLOW:
1. Type course/treatment name
2. See dropdown with existing terms (if any)
3. Click 'Save in Master' to add new term
4. Modal opens with name pre-filled
5. Enter SNOMED/ICD codes (optional)
6. Save → Auto-populates input + master_id
7. Click '+ADD Row' to add to discharge

BENEFITS:
- Consistent UI across Surgery/Procedure/Course sections
- Fast term entry without leaving form
- Master library builds during workflow
- ABDM compliance with code support
- Reusable terms across discharges
2026-06-06 06:53:27 +05:30
5aad2b0950 Fix database error in complaint field update - remove non-existent updated_at column
BUGFIX: Database error when saving editable complaint fields

PROBLEM: After adding X-Requested-With header, the request reached
the controller but threw 'Database error' when trying to update the
complaint field.

ROOT CAUSE: The ipd_discharge_complaint table does not have an
'updated_at' column. The update query was trying to set:
  - comp_report or comp_remark (correct)
  - updated_at (does not exist) ← DATABASE ERROR

INVESTIGATION: Checked how complaint rows are inserted elsewhere in
the codebase (line 4117-4130). The table has 'update_by' column for
tracking changes, not 'updated_at'.

SOLUTION:
1. Removed hardcoded 'updated_at' => date(...) from update data
2. Only update the target field (comp_report or comp_remark)
3. Conditionally set 'update_by' if column exists (audit trail)
4. Use session full_name for user tracking

Now editable complaint fields save successfully without database errors.
2026-06-06 05:33:18 +05:30
ddec3cec69 Fix editable complaint fields - attach handlers after section reload
BUGFIX: Event handlers were only attached on initial page load

PROBLEM: After implementing editable complaint fields, the inputs
wouldn't become editable when adding new complaints via the Smart
Complaints Picker. The event handlers were only attached once on
page load, not after the section was dynamically reloaded.

ROOT CAUSE: When clicking Add or AI Draft buttons, the form submits
and the section-complaints area is reloaded from server. The new
complaint rows had the input fields but no event handlers attached.

SOLUTION:
1. Moved event handler attachment logic into initComplaintTools()
   function as new attachComplaintFieldHandlers() helper
2. This function is automatically called after section reload
3. Clone-and-replace pattern to prevent duplicate event handlers
4. Fixed table name: ipd_discharge_complaint (not ipd_discharge_comp)

FLOW:
- Add complaint → section reloads → initComplaintTools() runs →
  attachComplaintFieldHandlers() attaches blur/keydown handlers →
  editable fields work

Now clicking on complaint name/remark inputs works for both:
- Existing complaints (on page load)
- Newly added complaints (after section reload)
2026-06-06 05:18:35 +05:30
2e6bff35a0 Make IPD discharge complaint names and remarks editable like OPD form
FEATURE: Inline editing for discharge complaint table

PROBLEM: In IPD discharge form, complaint names and remarks were
read-only after adding. Unlike OPD consult form where you can edit
complaint names directly in the table.

SOLUTION:
1. VIEW Changes (discharge_create.php):
   - Changed complaint name and remark columns from static <td> to editable <input>
   - Added data attributes for complaint ID and original values
   - Added CSS classes: discharge-complaint-name-input, discharge-complaint-remark-input

2. JAVASCRIPT Changes:
   - Added saveComplaintField() function for AJAX updates
   - Event handlers on blur to save changes
   - Enter key support to blur and save
   - Visual feedback: green border on success, red on error
   - Auto-updates original value after successful save

3. CONTROLLER Changes (Ipd_discharge.php):
   - Added update_complaint_field() method for AJAX endpoint
   - Updates ipd_discharge_comp table (comp_report or comp_remark)
   - Returns JSON success/error response

BENEFITS:
- Same user experience as OPD consult form
- Edit complaints/remarks without page reload
- Immediate feedback on save success/failure
- Type correction and updates without removing and re-adding rows
2026-06-06 05:12:23 +05:30
a76f0dd9e7 Make pain scale more compact for prescription layout
Reduced sizes:
- Table width: 100% to 60%
- Debug text: 10px to 8px
- Triangle: 18px to 12px
- Number boxes: 14px to 10px with 3px padding
- Border: 3px to 2px for selected
- Labels: uniform 7px font
- Reduced all margins and spacing

Still maintains clear B&W visibility with triangle, gray background, and bold border.
2026-06-06 04:21:56 +05:30
6259001aec Fix emoji rendering issue - use PDF-safe symbols instead
PROBLEM: Emojis don't render in PDF (showing as empty boxes)

SOLUTION:
- Use down-pointing triangle (▼) using HTML entity &#9660;
- This Unicode character renders properly in mPDF/PDF generators
- Darker gray background (#cccccc) for better B&W visibility
- Bold 3px border on selected box
- Larger font and padding for selected number

Visual indicators that work in B&W printing:
- Triangle (▼) above selected level
- Dark gray shading on selected box
- Bold border on selected box
- Bold text for selected label
2026-06-06 04:19:20 +05:30
a047955c7c Add emojis to pain scale for clear black & white printing
PROBLEM: Color coding not visible in black & white printers

SOLUTION:
- Added emoji indicators: 😊 😐 😣 😖 😭 for pain levels 0-4
- Changed colors to black/white/gray for B&W compatibility
- Emoji shows above selected pain level (larger size)
- Bold 3px border on selected box (visible in B&W)
- Light gray background on selected box

Now pain scale is clear even in monochrome printing!
2026-06-06 04:14:12 +05:30
cad5730182 Disable static PNG pain scale images, use dynamic HTML instead
PROBLEM: Static pains_scale_0-4.png files all look identical (just gradient)
so users can't tell which pain level is selected.

SOLUTION: Comment out PNG file checking code to force use of dynamic HTML
with arrow indicator, colored backgrounds, and bold borders.

Now {{painscale_img}} will show:
- Debug line: 'Pain Level: X - Label'
- Down arrow (▼) above selected level
- Colored background (green to red) on selected box
- Bold 3px border on selected box
- Different pain values will have visibly different displays
2026-06-06 04:07:16 +05:30
e0c44e79b1 Add debug info to pain scale image showing actual value
- Add 'Pain Level: X - Label' text above pain scale for debugging
- Helps identify if pain_value is being read correctly from database
- Fix comparison to use strict equality check for  ===
- User can now see which pain level is actually being rendered
2026-06-06 03:59:14 +05:30
a14011e11c Improve pain scale visual indicator for better clarity
- Change checkmark to down arrow (▼) for better visibility in PDFs
- Increase arrow size to 20px and make it bold
- Use white background for non-selected boxes for stronger contrast
- Add thick black border (3px) on selected level for emphasis
- Selected box shows colored background with white text
- Increase selected label text size and make it bold black
- Clear visual distinction between selected (value 2 vs 4) levels now
2026-06-06 03:54:51 +05:30
5e929c858e Fix H_logo placeholder not being replaced in OPD print
- Add fallback to 'logo.png' when H_logo is not set in database or constants
- Prevents {{H_logo}} placeholder from appearing as literal text in print/PDF
- Resolves 400 Bad Request error when browser tries to load unreplaced placeholder
- Ensures prescription templates always have a valid logo path
2026-06-06 03:43:31 +05:30
a5ccd71714 Enhance pain scale image with visual tick indicator
- Add checkmark (✓) above the selected pain intensity level
- Use color gradient from green (No Pain) to red (Worst) for better visual clarity
- Highlight selected level with colored background and white text
- Thicker border on selected level for better emphasis
- Bold label text for selected intensity
- Makes pain scale selection immediately visible in printed/PDF prescriptions
2026-06-06 03:11:25 +05:30
8ef46cddb1 Add permission for Admin to edit patient name anytime
- Add billing.patient.edit-name-anytime permission to AuthGroups
- Update patient edit time restriction from 12 hours to 24 hours
- Modify Person_Edit_V to check for edit-name-anytime permission
- Admin can now edit patient name field (input_name) even after 24-hour window
2026-06-05 17:33:31 +05:30
6314bafa29 Combine textarea notes and test list into single {{investigation}} placeholder
Modified {{investigation}} to show both:
1. Textarea content (advise_investigation_notes) if present
2. Comma-separated test list from opd_prescription_investigation table

Both sources combined with newline separator when both exist.
{{Tadvise_test_list}} still available separately for backward compatibility.

Example combined output:
USG WHOLE ABDOMEN
CECT ABDOMEN
PAC
COMPLETE CARDIAC CHECK UP
PAP SMEAR
CBC (Complete Blood Count), ECG (Electrocardiogram), HBA1C, HBSAG, HCV, HIV I & II (Elisa), Liver Function Test (LFT), PT/INR, Renal Function Test (RFT), Urine Routine & Microscopy, X-Ray Chest (PA View)
2026-06-05 16:04:01 +05:30
a1fbf50f3f Change {{Tadvise_test_list}} to comma-separated format (not bullet list)
Changed placeholder behavior to match user requirements:
- {{investigation}} = textarea content (advise_investigation_notes) only
- {{Tadvise_test_list}} = comma-separated test names from table

Removed HTML bullet list formatting. Now outputs plain comma-separated text.

Example output:
CBC (Complete Blood Count), ECG (Electrocardiogram), HBA1C, HBSAG, HCV,
HIV I & II (Elisa), Liver Function Test (LFT), PT/INR, Renal Function Test (RFT),
Urine Routine & Microscopy, X-Ray Chest (PA View)

Both placeholders are independent and can show content simultaneously.
2026-06-05 15:59:16 +05:30
0b865f41cd Add textarea fallback for {{Tadvise_test_list}} placeholder
When opd_prescription_investigation table is empty but investigation
textarea has content, parse textarea content (split by newlines) to
populate the test list.

This handles cases where tests are entered as free-text in the
"Advise Investigation" textarea instead of selecting from master list.

Parsing logic:
- Try rx_investigations table first
- If empty, split investigation textarea by newlines
- Filter out empty lines and 'null' values
- Build HTML bullet list from either source

Example textarea content:
USG WHOLE ABDOMEN
CECT ABDOMEN
PAC
COMPLETE CARDIAC CHECK UP
PAP SMEAR

Will render as:
• USG WHOLE ABDOMEN
• CECT ABDOMEN
• PAC
• COMPLETE CARDIAC CHECK UP
• PAP SMEAR
2026-06-05 15:55:34 +05:30
1ca2dbce4c Add error handling and debug mode for OPD PDF rendering
Added try-catch around mPDF WriteHTML to catch rendering errors.
Changed debug_html mode to output as text/html for better preview.
Logs mPDF errors and returns user-friendly error message.

This will help diagnose blank page issues with {{Tadvise_test_list}} placeholder.
2026-06-05 15:38:26 +05:30
a540581bf9 Fix {{Tadvise_test_list}} to always populate from rx_investigations
Previous implementation only built test list when investigation textarea
was empty, preventing {{Tadvise_test_list}} from showing when textarea
had content.

Changes:
- Separated test list building from textarea population logic
- {{Tadvise_test_list}} now always populates when rx_investigations exists
- {{investigation}} still gets comma-separated fallback when textarea empty
- Both placeholders now work independently

Test list HTML output format:
<ul style="margin:3px 0 0 16px;padding:0;list-style-type:disc;">
  <li>CBC (Complete Blood Count)</li>
  <li>ECG (Electrocardiogram)</li>
  <li>HBA1C</li>
</ul>
2026-06-05 15:28:01 +05:30
6f6286f427 Add {{Tadvise_test_list}} placeholder for investigation test names
Created new OPD template placeholder to display investigation test names
as a formatted HTML list, separate from the textarea {{investigation}}.

Changes:
- app/Controllers/Opd.php:
  * Added $rxInvestigationTestList variable in buildLegacyDashboardTemplateVars()
  * Builds HTML <ul> list from rx_investigations test names
  * Added 'Tadvise_test_list' token to return array

- app/Views/billing/opd_template_builder.php:
  * Added 'Tadvise_test_list' to $opdConsultSet placeholder list
  * Now appears in "OPD Consult" group in template builder

Usage in OPD templates:
- {{investigation}} = comma-separated test names (for textarea)
- {{Tadvise_test_list}} = formatted HTML bullet list of test names (for print/display)

Example output:
<ul style="margin:3px 0 0 16px;padding:0;list-style-type:disc;">
  <li>CBC (Complete Blood Count)</li>
  <li>USG WHOLE ABDOMEN</li>
  <li>ECG (Electrocardiogram)</li>
</ul>
2026-06-05 15:15:15 +05:30
a572bbabae Simplify org-case queries to match CI3 pattern
Changed from complex string comparisons to simple integer comparisons matching legacy CI3 code:

OPD query (CI3 pattern):
- OLD: o.insurance_case_id = cast(c.id as char) OR o.insurance_case_id = c.case_id_code
- NEW: o.insurance_case_id = c.id (integer comparison)

Invoice query (CI3 pattern):
- OLD: i.insurance_case_id = c.id OR i.insurance_case_id = c.case_id_code (with NULL/0 checks)
- NEW: i.insurance_case_id = c.id (integer comparison)

Schema notes:
- opd_master.insurance_case_id: int(11)
- invoice_master.insurance_case_id: varchar(50) (but stores numeric IDs)

MySQL varchar→int conversion handles this correctly:
- '4997' → 4997 (matches)
- '0' → 0 (doesn't match 4997)
- 'C26060004997' → 0 (doesn't match 4997)

Applied to:
- getOrganizationCaseInvoiceRows() union query
- updateOrgTotals() aggregate queries
- search() case list query
2026-06-05 14:14:22 +05:30
ba9d17d5e6 Fix org-case invoice query: exclude empty insurance_case_id
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)
2026-06-05 14:09:26 +05:30
4c5e0748bb Revert patient ID fallback - use insurance_case_id only 2026-06-05 13:55:50 +05:30
e80e18600d Fix org-case invoice scoping 2026-06-05 13:49:58 +05:30
6e3a355e03 Fix org case invoice and discharge PDF rendering 2026-06-05 13:43:19 +05:30
9c295c55c8 fix(discharge): enforce pdf response and sanitize template html 2026-06-05 12:03:47 +05:30
499a9bea31 fix(orgcase): fallback invoice linkage by patient and case 2026-06-05 11:45:01 +05:30
bd820a7939 fix(orgcase): use insurance amount1 in union invoice query 2026-06-05 11:37:23 +05:30
e7d6dd88d2 fix(orgcase): avoid missing discount column in union query 2026-06-05 11:34:52 +05:30
9f1d5b93e6 fix(orgcase): restore legacy union invoice rows 2026-06-05 11:32:01 +05:30
48222bb689 fix(orgcase): include OPD rows linked by case code 2026-06-05 11:27:24 +05:30
561adb9647 feat(discharge): add department and time placeholders 2026-06-05 11:05:00 +05:30
23fd1bf73f fix(discharge): render html fragments and reorder sections 2026-06-05 10:42:14 +05:30
0b05d7284c feat(discharge): support section placeholders 2026-06-05 10:24:31 +05:30
472b8367d9 fix(discharge): remove blank-header fallback and improve auto summary 2026-06-05 09:50:58 +05:30
3666875782 fix(discharge-pdf): suppress borders for border=0 tables 2026-06-05 08:39:48 +05:30
a076d48859 fix(discharge): apply latest controller adjustments 2026-06-05 08:31:02 +05:30
8f57288d2a fix(discharge): apply latest Ipd_discharge updates 2026-06-05 08:29:11 +05:30
c9c70a9ce5 fix(discharge): support borderless medication table in preview and PDF 2026-06-05 08:15:33 +05:30
7527fc315a fix(discharge): apply latest controller updates 2026-06-05 08:04:31 +05:30
b47b41ce8a fix(discharge-pdf): remove auto title/template block from body 2026-06-05 07:40:43 +05:30
f341e8e76e fix(discharge-template): make delete endpoint reliable for URL and AJAX 2026-06-05 07:37:39 +05:30
a169ab174b fix(discharge): render header/footer hospital placeholders in PDF 2026-06-05 07:33:07 +05:30
171ff50155 fix(template): backfill discharge template columns for legacy schemas 2026-06-05 07:20:43 +05:30
fdb7c15f85 Fix discharge template page edit flow and AJAX save/delete 2026-06-05 07:12:58 +05:30
e6ffebb96d Render discharge PDF with content-only body and remove duplicate top meta blocks 2026-06-05 07:05:25 +05:30
21e662a0e6 Fix duplicate discharge summary header when using content placeholder 2026-06-05 06:47:39 +05:30
ecb55e7329 Add page settings and header footer support to discharge templates 2026-06-05 06:22:13 +05:30
b6a2e956d8 Remove heading from combined NABH panel placeholder 2026-06-05 06:05:06 +05:30
806044ff93 Add single conditional NABH panel placeholder 2026-06-05 06:00:43 +05:30
8bfd11ccda Persist consult NABH fields via remarks fallback 2026-06-05 05:53:24 +05:30
c4a6e95933 Add explicit OPD NABH allergy raw and block placeholders 2026-06-05 05:47:16 +05:30
14fb1fd400 Fix OPD placeholder collisions for vitals and allergy blocks 2026-06-05 05:29:58 +05:30
51daaa989a Fix OPD pain/allergy placeholders and hide No Pain block 2026-06-05 04:51:05 +05:30
dc2a0da1ee Use mPDF-safe mm spacer blocks for OPD section gaps 2026-06-05 04:26:23 +05:30
dbda578d68 Harden OPD block spacing and add debug_html output mode 2026-06-05 04:18:48 +05:30
f358bbd66c More spacing between OPD print blocks; add margin around medicine table 2026-06-05 04:13:21 +05:30
3a06c32dc5 Increase spacing between OPD print placeholder blocks 2026-06-05 04:08:20 +05:30
6bdef9bb9d Improve OPD print block typography for professional output 2026-06-05 03:54:52 +05:30
a1ba8f0e6b Enhance OPD template placeholders and list rendering 2026-06-05 03:48:24 +05:30
700741ab9b Fix billing case creation reusing old records 2026-06-04 15:55:08 +05:30
c692340bb2 Store ABDM bundles in health records 2026-06-03 11:05:40 +05:30
45abd3ca76 Store ABHA ID and ABHA address separately 2026-06-02 06:00:35 +05:30
510d121478 Normalize OPD preview bundle_type from profile 2026-06-01 14:04:44 +05:30
c68816ce57 Upgrade regenerated OPD bundle_type to OPConsultRecord 2026-06-01 14:02:23 +05:30
6f312dd0d8 Add manual GET wrapper for FHIR regenerate 2026-06-01 14:00:02 +05:30
b0e3459c19 Add ABDM careContexts and OPD visit key 2026-06-01 13:54:56 +05:30
00c45ea7c4 Accept OPConsultRecord bundle lookups 2026-06-01 13:34:35 +05:30
b70e88dd75 Use OPConsultRecord for OPD bundles 2026-06-01 13:31:53 +05:30
33fc87ac88 Fix OPD FHIR submit record reference 2026-06-01 13:29:10 +05:30
9de803ace7 Send ABDM HFR ID only 2026-06-01 13:24:59 +05:30
e8ec06e8f8 Harden ABDM health record push payloads 2026-06-01 13:23:54 +05:30
07ed8ff305 Sanitize OPD FHIR patient name placeholders 2026-06-01 10:57:30 +05:30
f079f32f58 Restore legacy pharmacy reports and fix net/payment totals 2026-06-01 10:53:27 +05:30
252f911fad Add pharmacy invoice permissions and discount print fixes 2026-06-01 10:13:40 +05:30
b12652d6e0 Align ABDM bridge workflow APIs and add report doctor mapping 2026-06-01 07:02:34 +05:30
e1d9e85e64 Fix FHIR DiagnosticReportRecord datetime and practitioner quality 2026-06-01 06:01:24 +05:30
7595f9fd29 fix(ipd-discharge): make lab date query compatible with only_full_group_by 2026-05-31 21:43:57 +05:30
701111b75e fix(patient): avoid queue_no select on legacy opd_master schema 2026-05-31 21:02:55 +05:30
0ebf8d2a8a ABDM: enforce PDF-backed report submit and improve gateway tracking 2026-05-31 04:17:39 +05:30
7253fa0cca Improve radiology template workflow and editor stability 2026-05-30 18:01:20 +05:30
78c23af7e5 Checkpoint: pathology panel modal workflow, gateway component search, and ABDM-style component/print editors 2026-05-30 06:32:30 +05:30
218d7f7e50 fix(pharmacy): calculate invoice unit rate from mrp and packing 2026-05-26 13:21:36 +05:30
298647b80b fix(pharmacy): finalize product page panel toggle and GST selector behavior 2026-05-26 13:07:46 +05:30
89a4053ede fix(drug-master): keep search shell visible with nested sub panel 2026-05-26 06:20:56 +05:30
fc2ccc91c2 fix(drug-master): keep add edit flow in medical-main container 2026-05-26 06:15:14 +05:30
4ed366ccb2 feat: commit all pending page and ABDM gateway updates 2026-05-26 06:04:34 +05:30
c97db078a9 fix(product-edit): use short formulation master and manufacturer payload name 2026-05-26 06:02:26 +05:30
e5899e59ac Fix drug autocomplete to show medicine name over identifiers 2026-05-25 14:38:06 +05:30
0558ac5a2e Pharmacy: add ABDM drug terminology autocomplete + canonical mapping 2026-05-25 13:57:56 +05:30
12cacc3a9c Pharmacy drug master: switch to AJAX DataTable search 2026-05-25 12:47:14 +05:30
e15d876a3f Fix ABDM OPD HMS patient profile link route to person_record 2026-05-25 12:14:23 +05:30
c590087a60 feat(abdm-opd): editable pre-save patient form for Register OPD 2026-05-24 07:16:32 +05:30
b352073ec6 feat(abdm-opd): duplicate-aware Register OPD flow with existing/new patient confirmation 2026-05-24 07:04:42 +05:30
23cca1f9ba feat(abdm): proper FHIR bundles for lab reports and IPD discharge
- FhirR4Builder: rewrite buildLabReportBundle() with DiagnosticReportLab
  profile, structured Observation valueQuantity/valueString, reference
  ranges, interpretation codes, Binary+DocumentReference for HTML report,
  Encounter resource, HFR-based bundle identifier system

- FhirR4Builder: rewrite buildDischargeSummaryBundle() with optional
  Practitioner/Organization params, structured ABDM sections (chief
  complaints 422843007, medical history 1003642006, investigations
  721981007, procedures 1003640003, medications 721912009, follow-up
  736271009), HFR-based bundle identifier system

- AbdmGateway: shareIpdDischargeBundle() now builds a real
  DischargeSummaryRecord FHIR bundle and posts via pushRecord()
  (POST /v3/records/push) instead of the stale shareIpdDischargeBundle()

- AbdmGateway: shareDiagnosisReportBundle() now builds a real
  DiagnosticReportRecord FHIR bundle and posts via pushRecord()
  instead of the stale shareDiagnosisReportBundle()

- AbdmGateway: add getHospitalProfileForFhir() and mapLabTypeToTitle()
  helpers; fix pre-existing undefined \ bug in
  getActiveConsentRecord()

- Add ABDM_FHIR reference package, AbdmBridgeLog controller/view,
  bridge record migration, debug scripts and misc UI/settings updates
2026-05-23 04:41:59 +05:30
1b6f2c2db7 feat: Add Submit to ABDM button on FHIR bundle preview
- POST Opd_prescription/fhir_bundle_submit endpoint:
  loads stored FHIR bundle, fetches patient/OPD/doctor context,
  calls EAtriaBridgeConnector::pushRecord to push to bridge
- Standalone preview page (/Opd_prescription/fhir_bundle_preview/N):
  added Submit to ABDM Bridge button with CSRF-safe AJAX + inline
  success/error alert
- FHIR modal in task_board.php: added Submit to ABDM button next
  to Copy JSON; JS reads _fhirOpdId/_fhirSessionId and posts to
  fhir_bundle_submit with CSRF token refresh
2026-05-22 15:54:13 +05:30
0fe556f37e fix: preserve doctor original text in FHIR form; add live complaint/diagnosis terms to preview 2026-05-20 03:14:17 +05:30
78060d03c8 feat: FHIR form view — inline diagnosis SNOMED edit + show doctor's original text 2026-05-20 03:02:03 +05:30
70bc85ae0c fix: restore advice_search() method declaration lost in prior commit 2026-05-20 02:53:48 +05:30
4250000d43 feat: FHIR form view — inline complaint SNOMED edit with live search and save 2026-05-20 02:49:36 +05:30
cd18551ce2 feat: FHIR bundle — use complaint_snomed_json for coded complaints (SNOMED + severity + duration) 2026-05-20 02:08:01 +05:30
32c1dc20e1 feat: Clinical Master workspace — Complaints + Diagnosis edit with SNOMED CT search 2026-05-20 01:25:01 +05:30
e33b0809a0 fix: fhir_bundle_preview returns JSON for AJAX (modal) requests, HTML for direct browser 2026-05-20 00:56:56 +05:30
ed4e7c1fe4 feat: ABDM task board — remove All, rename ABHA Update, add OPD Book + OPD Consult Publish sections 2026-05-20 00:29:00 +05:30
02ec0034d7 fix: stop injecting Diagnosis SNOMED lines into Prescription textarea — data is in diagnosis_json; strip legacy lines on save 2026-05-19 23:46:44 +05:30
e275a20946 fix: remove JS-style \u00a0 from PHP PCRE duration regex (PCRE2 does not support \u) 2026-05-19 22:38:33 +05:30
b702ff6fdc feat: complaint Extract Codes button with SNOMED chip review panel
- Add 'Extract Codes' button to complaint lookup input
- Parse free-text with duration/severity extraction (regex: 3 days, moderate etc)
- Call Opd_prescription/complaints_extract endpoint -> local SNOMED FULLTEXT
- Render inline chip cards: term, concept_id, duration, severity, confidence%
- Doctor clicks confirm (green tick) or reject (red x) per chip in seconds
- Confirm pre-fills duration+severity in complaint table row automatically
- 'Confirm All' bulk action; Dismiss clears panel
- Add complaints_extract controller method + parseComplaintFreeText helper
- Add route Opd_prescription/complaints_extract
2026-05-19 22:30:23 +05:30
a56e8a5776 feat: SNOMED background coding pipeline + ABDM Coding Panel
- Add opd_coding_queue + opd_snomed_suggestions migrations
- Add ProcessSnomedCoding spark command (cron: snomed:process-coding)
  Extracts clinical phrases, matches local SNOMED FULLTEXT, saves suggestions
- Add AbdmCodingPanel controller: index/review/confirm/reject/correct/mark_fhir_ready/tip_check
- Add coding_panel + coding_panel_review views (Bootstrap 5, AJAX actions)
- Inject queue trigger in opd_prescription_save (fail-open, ON DUPLICATE KEY)
- Add consult form tip badge: polls tip_check 4s after save, shows review link
- Add AbdmCodingPanel routes behind abdm permission filter
- Various ABDM gateway, FHIR, ABHA, SNOMED library updates
2026-05-19 20:40:27 +05:30
0628f8f813 feat: ABDM OPD Queue + ABHA Register flow + patient ABHA search fix
ABDM OPD Queue (today):
- New EAtriaBridgeConnector: opdQueueFetch/opdTokenCreate/opdTokenUpdateStatus + patch() helper
- New AbdmOpdQueue controller: index/list/fetchQueue/createToken/updateTokenStatus/processScannedToken
  - fetchQueue syncs gateway tokens into abdm_opd_tokens (local DB) and enriches with HMS patient data
  - processScannedToken auto-finds/creates patient_master record from ABHA scan data, marks token CALLED
- New migration: abdm_opd_tokens table (gateway_token_id, source, status, patient_id, opd_id, processed_at)
- New view: abdm/opd_queue.php - reception screen with auto-refresh 30s, HMS Patient column (green row when OPD registered)
- Sidebar: ABDM OPD Queue nav link added
- Routes: AbdmOpdQueue with abdmPermFilter

ABHA Register tab (earlier this session):
- New Abha controller: initiate/verifyOtp/communication/verifyCommOtp/validateAbha/card + autoCreateOrFindPatient
- New views: abha/card.php, partials/abha_create_panel.php, partials/abha_otp_modal.php
- Patient_V.php: ABHA Register tab with 4-method wizard (ABHA number, QR scan, facility QR, mobile OTP)

Patient ABHA search fix:
- Patient::search() now detects ABHA column (abha_id/abha_no/abha/abha_address) and searches by it

ABDM Bridge infrastructure:
- EAtriaBridgeConnector: new connector for e-atria.in ABDM bridge gateway
- AbdmConnectorFactory/Interface updated
- AbdmGatewaySettings controller + view
- SNOMED/CSNOTK terminology service skeleton
- Finance payout OPD consult views
- Migration: AddAbdmPushFieldsToOpdAndPatient, CreateSnomedCoreTables
- Docs: abdm/ API specs, architecture, gateway guides
2026-05-16 04:21:31 +05:30
f311d50745 OPD consult: add women history fields, persist in history, update print sections 2026-05-12 12:52:13 +05:30
38a63a628b abdm: add connector adapter pattern (Interface/Factory/Dreamsoft/Direct) + refactor AbdmGateway 2026-05-08 23:10:24 +05:30
5d5c9656ea billing: improve patient name display on consult form and history page 2026-05-08 13:49:37 +05:30
fbb03a6abb billing: redesign ABHA wizard, enhance patient info panels and consult page photo/layout 2026-05-08 13:29:57 +05:30
3c4dff6285 Improve doctor document workflow and print performance 2026-05-06 02:06:18 +05:30
be6f0cd6d0 Set OPD appointment list default order to descending 2026-05-05 22:56:57 +05:30
7ab37ad80d Finance: separate OPD Consult and Doctor Charges payout screens; compact dashboard cards; add IPD payout tracking migration 2026-05-01 21:02:57 +05:30
44dee3e3d5 Show IPD payout pool as invoice-level rows under IPD grouping 2026-04-30 02:09:26 +05:30
ced87420b4 Remove payout invoice column and align datatable ordering for grouped pool 2026-04-30 02:05:07 +05:30
e72e5590ff Fix invoice table date filtering to return matching rows 2026-04-30 01:58:19 +05:30
36d3fa843b Implement medical store credit payout workflow and optimize payout pool DataTable grouping 2026-04-30 01:42:03 +05:30
ec6ceaea98 Add dedicated Save Settings button for user preferences
- Add separate Save Settings button below User Settings card
- Create myProfileSaveSettings controller method for dedicated settings save
- Settings save endpoint: POST /my-profile/save-settings
- Validates sidebar_auto_hide_seconds (0-60 range)
- Provides immediate feedback: success/error message display
- Separate from profile photo and password updates
- Message auto-hides after 2 seconds on success
2026-04-28 13:54:46 +05:30
5717763496 Add user-based sidebar auto-hide setting, movable from hospital default
- 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)
2026-04-28 13:47:46 +05:30
0aa0edbbce Fix OPD confirm payment flow and DataTable initialization
- Opd.php: mode-0 (zero amount) no longer inserts payment_history row
  and skips HealthPlix sync for faster confirm
- Opd.php: added spid-based idempotency for cash/card to prevent
  duplicate payment_history rows on retry
- Opd.php: invoice view hides 0-amount payment_history rows
- opd_appointment_list.php: fix isDataTable call (DataTable -> dataTable)
- jquery.dataTables.min.js: replace non-functional shim with real
  DataTables 1.13.8 (supports ext.search, isDataTable, rows() API)
2026-04-28 12:01:53 +05:30
baba5521dd Fix dashboard and OPD counts for DATETIME appointment_date 2026-04-28 11:23:06 +05:30
5226fde8a0 Fix OPD appointment datetime display and date filtering 2026-04-28 10:59:04 +05:30
6a5519388e Make HealthPlix Doctor Identifier field optional in Doctor Master 2026-04-28 08:22:00 +05:30
bd274a3fc3 Add OPD appointment time capture and storage with date+time display 2026-04-28 07:59:47 +05:30
cef10f70e1 Reflect actual HealthPlix fetch secret save state 2026-04-28 07:40:22 +05:30
cab7bbd3a6 Fix HealthPlix fetch parsing and refine sidebar headings 2026-04-28 07:28:34 +05:30
cc5018568b Add HealthPlix fetch callback endpoint and Apache proxy rollout templates 2026-04-28 06:29:29 +05:30
d230d8960d feat: add configurable sidebar auto-hide in hospital settings 2026-04-27 14:32:31 +05:30
6ae9a3516f feat: add HealthPlix OPD sync flow with settings, diagnostics, and sync ID persistence 2026-04-27 08:32:51 +05:30
f610adf2fe feat: add user profile photo upload and show avatar in header 2026-04-25 09:52:21 +05:30
d02244444e finance/storestock: implement cash submission audits, bank settlements, and opd payout tracking 2026-04-22 10:53:20 +05:30
7e4903bd68 billing: add patient history action and legacy-style OPD history view 2026-04-22 10:33:29 +05:30
eb13872f43 Finance bank audit: settlement tab/filter refinements, bank-only selection, and summary metrics 2026-04-21 19:06:16 +05:30
fbbecee3b4 feat(ipd-charges): group delete, sort order, Up/Down buttons, foldable billing panels
- 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
2026-04-18 06:56:38 +05:30
07916f3baf Allow same medicine name with different formulation in OPD save 2026-04-17 09:48:30 +05:30
1cea1495fc Fix OPD scan delete button for direct file-list page and AJAX modal 2026-04-17 04:41:45 +05:30
a0b724e30d Fix serve_legacy_upload to also check public/uploads/ (FCPATH) 2026-04-17 04:20:49 +05:30
58ddd77d42 Add fallback route to serve legacy CI3 uploads from project-root uploads/ 2026-04-17 04:16:08 +05:30
11fe14089d Stop auto-filling prescription remarks from structured allergy fields 2026-04-17 03:50:01 +05:30
ec872c984c Strengthen OPD autocomplete normalization for spacing and punctuation variants 2026-04-17 03:41:01 +05:30
47423a7d38 Normalize OPD autocomplete suggestions and add one-time cleanup command 2026-04-17 03:31:33 +05:30
1084ef8875 Fix: {{advice}} prints as-is (no Hindi/AI conversion); fix Schema Diff truncation 2026-04-16 12:31:42 +05:30
aae6211f48 Add investigation shortcuts manager panel 2026-04-14 21:51:49 +05:30
57397d80e1 Fix OPD print remarks leaking NABH allergy lines 2026-04-14 08:34:46 +05:30
5801b5d276 Refine {{medical}} table widths and instruction row styling 2026-04-14 07:50:50 +05:30
b97bb74a5d Reformat {{medical}} rows with wide instruction line 2026-04-14 07:43:07 +05:30
0b2ae6ccc1 Broaden consult search candidates for phonetic medicine matches 2026-04-13 13:04:01 +05:30
992fd83ff2 Normalize separator variants in consult medicine SQL search 2026-04-13 12:57:16 +05:30
9e30d69487 Add phonetic matching for consult medicine search 2026-04-13 12:54:33 +05:30
05ff049526 Improve consult medicine search normalization and duplicate blocking 2026-04-13 12:46:42 +05:30
f99f48b62f fix: restrict scan delete to 24h or same date 2026-04-11 04:49:59 +05:30
7233f5979e feat: auto visit-done on scan save and add scan delete actions 2026-04-11 04:45:45 +05:30
f748224cd0 fix: count OPD visits up to printed opd date 2026-04-10 21:30:47 +05:30
920f1033c0 fix: compute print total_no_visit from opd_master records 2026-04-10 21:28:15 +05:30
d16a363a92 fix: recalculate IPD billing on panel open, bill-details, and print 2026-04-10 21:11:24 +05:30
2c3552ac07 fix: include medicine qty in {{medical}} consult print placeholder 2026-04-10 14:27:35 +05:30
5ed2bd13ae fix: include opd continuation template field in doctor template mappings 2026-04-10 13:42:23 +05:30
385183fbe2 feat: Add Print Cont. Paper template selection to Doctor Master 2026-04-10 13:19:47 +05:30
910f46b06c feat: add Doctor Master OPD validity editing with hospital fallback
- 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
2026-04-10 12:58:17 +05:30
eec0642466 fix: OPD running validity period no longer extends per running visit
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
2026-04-10 12:48:28 +05:30
21ddeefe40 fix: Running OPD zero-value validity, update_doc_field HTTP 500, PDF Unicode font (Devanagari)
- Opd.php showfee(): exclude zero-amount OPD from validity window query
- Opd.php confirm_opd(): anchor last_opdvisit_date to most recent paid OPD for zero-value running
- Opd.php buildOpdLetterPrintData(): use paid OPD start date for expiry on zero-value entries
- OpdModel.php insertOpd(): exclude fee_type=3/zero-amount from running_opd_id lookup; anchor visit count to paid OPD start when isZeroValueRunning
- DoctorDocument.php update_doc_field(): wrap in try/catch, schema-safe payload via filterPayloadByExistingColumns, structured JSON errors
- DoctorDocument.php create_final(): configure mPDF with FreeSans/FreeSerif (GNU FreeFont), useOTL=0xFF, autoScriptToLang=true for Devanagari/Hindi rendering
- doc_letterhead_print.php: add body/p/td/th font-family freesans for PDF Unicode output
2026-04-10 12:30:15 +05:30
433b89f426 Fix payment request receipt content and PDF print 2026-04-10 04:16:17 +05:30
385c977d88 Auto-mark OPD visited on consult save or print 2026-04-10 03:59:10 +05:30
6a0660cad7 Show patient age and gender in OPD list 2026-04-10 03:55:00 +05:30
c534a83ad2 Normalize OPD queue display per doctor day 2026-04-10 03:44:32 +05:30
7f131aeae8 Add OPD doctor/date update endpoint and invoice validation feedback 2026-04-09 19:47:57 +05:30
b4ae081d28 Add refer doctor filter to diagnosis report 2026-04-09 19:11:39 +05:30
aa2e092758 Add OPD Total Report with doctor/type/fee filters 2026-04-09 18:44:35 +05:30
7275d13500 Add OPD keyword manager and caret-aligned autocomplete 2026-04-09 06:25:03 +05:30
418fb3e5e7 Add cached consult autotype suggestions and doctor/master keyword save 2026-04-09 06:07:46 +05:30
b1d329e462 Port legacy OPD autotype suggestions for complaints, provisional diagnosis, and findings 2026-04-09 06:00:29 +05:30
e087b26fc6 Do not render default footer when document print template footer is blank 2026-04-09 04:45:02 +05:30
9fcb7c9ee1 Apply placeholder resolver to general document body in create_final and normalize escaped newlines 2026-04-09 04:32:44 +05:30
90ac310cf0 Port CI3 vitals chart and treatment chart forms to CI4 IPD form print (form_no 6 and 7) 2026-04-09 04:26:09 +05:30
5299a9d7c2 Resolve {{H_Name}} and other placeholders in document print custom header/footer HTML 2026-04-09 04:04:38 +05:30
5f35d22f86 Fix medicine search cache key format 2026-04-08 20:06:08 +05:30
2795e6255c Add medicine search DB indexes and prefix query optimization 2026-04-08 19:49:51 +05:30
fad0d89260 Speed up medicine autocomplete with cache and 10-row limit 2026-04-08 19:47:38 +05:30
935d6edd0b Keep IPD charges visible when optional tab queries fail 2026-04-08 11:52:27 +05:30
cbe861ad53 Guard IPD tab panel-data load to prevent remote ipd-charges 500 2026-04-08 11:48:48 +05:30
d003c67b1e Harden IPD charges tab render to avoid Whoops on remote 2026-04-08 11:45:25 +05:30
2977192017 Make IPD forms dynamic and stop stale OPD refresh polling 2026-04-08 11:41:33 +05:30
8bc9158e14 fix: support legacy doc_format schema in doctor document workspace
- Make docedit_load/doc_input_list/create_doc flows tolerant when doc_format_sub.active is missing\n- Guard master/sub insert/update payloads by existing DB columns to avoid SQL 500 on old dumps\n- Avoid hard dependency on created_at/updated_at/default_print_type print margin columns\n- Keep behavior unchanged on upgraded schemas while restoring compatibility with legacy production data
2026-04-08 10:10:05 +05:30
1a2dbf5366 feat: upgrade IPD Document Master to OPD-style print builder
- Add paper print settings to IPD templates (page size/custom size/margins)\n- Add Header HTML, Footer HTML, and Style (CSS) support\n- Update IPD PDF renderer to honor template paper settings and header/footer\n- Extend IPD placeholders with logo/QR support: {{H_logo}}, {{H_logo_abs}}, {{hospital_logo_html}}, {{qr_content}}, {{qr_code_html}}\n- Improve token rendering with robust curly placeholder parser for body/header/footer\n- Keep legacy sticker forms aligned with custom label dimensions and migrate old default rows
2026-04-08 07:56:43 +05:30
bca95f14e6 fix: {{medical}} prints Generic Name instead of Substitute in OPD consult print
Root cause: the fallback lookup from opd_med_master used
  $labelField = $masterSaltField ?? $masterGenericField
which preferred salt_name (the Substitute / other brand names field) over
genericname (the actual Generic Name / composition). If a prescription row's
inline genericname was empty, the Substitute string was written into it and
then printed as \"Salt/Generic\" in the {{medical}} block.

Fixes applied in three places:
1. Opd.php buildOpdLetterPrintData - master lookup now prefers genericname
2. Opd.php buildOpdLetterPrintData second loop - removed inline salt_name
   fallback that overwrote genericname with Substitute value
3. Opd.php buildLegacyDashboardTemplateVars - removed salt_name from the
   generic resolution chain used when rendering the medicine table HTML
4. Opd_prescription.php medicine list function - same preferGenericname fix
   and removed inline salt_name -> genericname overwrite"
2026-04-07 11:34:57 +05:30
2958f2e9b6 fix: queue no per-doctor-per-day isolation and stop auto-refresh on digest poll
- Queue No (Opd.php::autoCreateOpdQueue, Opd_prescription.php::opd_prescription_save
  and ::ensurePrescriptionSession): changed MAX(queue_no) query to JOIN through
  opd_master.doc_id instead of trusting opd_prescription.doc_id, ensuring queue
  numbering is strictly per-doctor per-day regardless of stale doc_id values in
  opd_prescription rows.

- OPD appointment list: replaced auto-reload-on-digest-change with a manual
  'Refresh' button. When the 8s digest poll detects new data the button turns
  yellow with a 'New' badge; the page only reloads when the user explicitly clicks
  it, preventing disruptive mid-session reloads."
2026-04-07 11:23:20 +05:30
16f3c95053 Fix OPD template builder sync and formulation formatting 2026-04-07 03:55:53 +05:30
19db43762d Enhance OPD and patient workflows with live updates and UX improvements 2026-04-07 03:27:39 +05:30
67664ab8ff fix: move confirmed opd appointments into waiting 2026-04-06 13:11:46 +05:30
ca4b4195aa fix: keep new OPD appointments in booked list 2026-04-06 12:51:11 +05:30
b03eb0064a fix: show booked queue actions in waiting list 2026-04-06 12:47:00 +05:30
44cb24c4e1 fix: restore legacy OPD queue workflow 2026-04-06 12:40:34 +05:30
f8cbaacfb0 perf: remove AI enrichment from consult new medicine save flow 2026-04-06 12:20:44 +05:30
30643c87f8 feat: add scan doc list modal and print medicine formulation prefix 2026-04-06 12:11:56 +05:30
2154af394c fix: build Next Visit chips from opd_nextvisit with date from today 2026-04-06 11:45:08 +05:30
f28fcf2717 feat: auto-create new consult medicines in OPD master with AI/local detail enrichment 2026-04-06 11:38:11 +05:30
1843460693 feat: restore Old Prescription panel with add-one/add-all into current consult 2026-04-06 11:24:11 +05:30
8a3157e579 fix: populate last_opdvisit_date token in OPD print templates with previous visit date 2026-04-06 10:42:03 +05:30
2fc4fbd82c fix: use Unicode-compatible Hindi fonts for IPD form PDF rendering 2026-04-06 09:17:48 +05:30
f09e16c3a2 fix: prevent provisional diagnosis from duplicating diagnosis token in OPD print 2026-04-06 08:38:35 +05:30
7e16ac92c2 fix: dynamic ABHA column SELECT in createOpdPrescriptionWorkTask (unknown column abha_no) 2026-04-06 00:01:08 +05:30
e049ddcf2b fix: dynamic ABHA column SELECT in openReportEditorPage to handle remote DB schema 2026-04-05 23:57:16 +05:30
062fc7ab32 feat: Add ABDM Task Board module with ABHA workflow
- Add ABDM sidebar heading and Task Board nav link
- Create migration 000040: abdm_work_tasks table
- Add AbdmTaskBoard controller with backfill methods
- Add AbdmWorkTaskService for task creation/deduplication
- Add AbdmGateway controller for ABDM API integration
- Separate task types: patient_abha_create vs patient_abha_update
- Add lab_report_publish and radiology_report_publish task types
- Patient.php: auto-create ABDM tasks on registration
- Diagnosis.php: auto-create tasks on report verify/finalize
- Task board UI: 7 filter buttons with default Unupdated ABHA view
- Fix SQL crash in backfillLabRadiologyTasks (dynamic column detection)
- Improve load_form AJAX error display with HTTP status + response text
- Add ABDM routes in Routes.php
- Add FHIR R4 builder library updates
- Add bridge sync service updates
2026-04-05 23:42:24 +05:30
9d88aaa2a6 Implement ABDM identity storage and align OPD consult/medicine dose masters 2026-04-04 17:26:40 +05:30
9d2f91e73a Pathology report list: optional hc_items filter with null-safe fallback 2026-04-03 16:15:23 +05:30
ab4b9a39f8 Pathology report list: exclude mixed ultrasound by requiring lab_repotests mapping 2026-04-03 16:09:50 +05:30
d9e4d50dc6 Pathology report list: include all lab_repo templates even if group mapping missing 2026-04-03 16:06:26 +05:30
721f374521 Pathology report list: show templates without strict hc_items join filter 2026-04-03 16:03:12 +05:30
259ea1331a Diagnosis: fix ONLY_FULL_GROUP_BY in edit test data query 2026-04-03 15:55:24 +05:30
fd28d6a01e IPD cash balance: fix date range picker submission and parser 2026-04-03 14:13:05 +05:30
eec58b546d OPD templates: render short description with nl2br 2026-04-03 13:59:57 +05:30
e009b748ca OPD templates: add doctor short description placeholder tokens 2026-04-03 13:46:10 +05:30
34f31aed6a Diagnosis: fix ONLY_FULL_GROUP_BY in lab search queries 2026-04-03 13:32:56 +05:30
435192f81a IPD payment receipt: fix modal loader, add PDF print route, and bank mode details 2026-04-03 13:29:03 +05:30
e282289227 Default new patient blood group to Not Define 2026-04-02 17:49:45 +05:30
d8f75b3a29 feat(stock): add modular hospital stock management with dashboard, masters, indents, purchase and reports 2026-04-02 10:28:38 +05:30
584c9ce59d Fix BedManagement controller header to restore bed-status route 2026-04-02 06:27:52 +05:30
7b7c9e510e Bed Status: graphic ward/floor map with patient search, colour-coded bed cards 2026-04-02 06:25:26 +05:30
7b04c8e419 Add Echo modality to diagnosis navigation and charge group setup 2026-04-02 05:12:08 +05:30
2b391705fe Rx print: persist and print Hindi advice from opd_advice 2026-04-01 20:23:10 +05:30
ddf8fd2345 Rx print: use regex sign extraction for dose Hindi lookup from opd_dose_shed 2026-04-01 20:13:10 +05:30
0d500d82b2 Rx print: fix dose translation (prefix match + one-time-a-day), consistent 11px Hindi font 2026-04-01 20:08:00 +05:30
caba6dc84b Rx print: professional font, vitals on one line, advice in Hindi 2026-04-01 20:01:38 +05:30
c3f07db430 Fix consult profile add: avoid duplicate investigation code 500 2026-04-01 19:33:55 +05:30
f4891c0bb4 Fix profile master data loading and remove city_auto_u migration 2026-04-01 19:22:03 +05:30
94e1253e40 Investigation Profile Master: CRUD and consult integration 2026-04-01 18:44:52 +05:30
d06fe77f03 Investigation Master: use legacy investigation key field 2026-04-01 18:33:20 +05:30
771fa64778 Investigation Master: CRUD, favourites, specialization filter 2026-04-01 18:26:33 +05:30
e27a69df5d OPD/IPD: add dosage defaults to medicine master form; make drug allergy non-mandatory (default: Allergies Not Known) 2026-04-01 18:12:25 +05:30
7ea22378f5 OPD medicine list: move DataTable to server-side ajax 2026-04-01 17:49:02 +05:30
c3bc8f89b8 OPD: simplify medicine list and reuse master dosage defaults 2026-04-01 17:40:50 +05:30
6b2c82e808 Map OPD dose Hindi labels from master tables 2026-04-01 08:46:29 +05:30
a9b5e76fc9 Improve OPD prescription print template variables 2026-04-01 07:58:48 +05:30
fe1156b68a Fix billing invoice balance/payment flow and deduction UI 2026-04-01 07:23:29 +05:30
3088d1fc85 Fix OPD print placeholders for consult fields
- Add fallback key resolution for complaints, diagnosis, provisional diagnosis, and finding examinations
- Expose placeholder aliases for mixed-case and lowercase template variables
- Keep provisional diagnosis precedence over diagnosis when present
2026-03-31 07:20:35 +05:30
af033c24e0 Add temporary debug logging to OPD paper settings save/read flow
Captures:
- Storage key being used
- Payload length
- Which candidate keys are checked
- Persistence verification results

Remove this commit after testing confirms the fix works
2026-03-31 06:55:59 +05:30
edd577e3e7 Fix OPD paper settings save failure: use short hashed keys + legacy fallback
- Shortened template-scoped paper setting keys to avoid s_name length limits in legacy schemas
- Added legacy key fallback so existing saved settings still load
- Updated rename/delete/reset flows to handle both new and legacy key aliases safely
- Restored corrupted buildOpdLetterPrintData method that broke class structure

This fixes the 'Unable to save OPD paper print settings' error when saving new templates
2026-03-31 06:55:06 +05:30
874d5ffba6 feat: add granular template permissions for role-based template access
- add new permissions:
  template.opd_print, template.pathology_print, template.diagnosis_print,
  template.document_print, template.ipd_document
- Template controller now accepts new permission keys (with backward-compatible fallbacks)
- IPD Document Master now has independent permission key (template.ipd_document)
- Template index tile visibility updated to use new granular keys
- OPD print template builder now honors template.opd_print permission
- preserve existing behavior via legacy permission fallbacks to avoid role breakage
2026-03-31 06:35:36 +05:30
f7b9a51c47 fix: sanitize noisy OCR output for OPD scan AI results
- add sanitizeExtractedScanText() to clean OCR text before analysis/storage
- strip non-ASCII/control noise that appears as mixed-script junk characters
- remove repeated junk tokens (e.g. ffffff, repeated words)
- add ECG-specific OCR normalization (KECG->ECG, Uniconfirmed->Unconfirmed, avt->aVL, VT->V1)
- apply sanitization to both OCR sources (document intelligence and vision fallback)
- keep fallback behavior when sanitization returns empty
2026-03-31 05:12:56 +05:30
cf299de505 feat: add Delete button to Rx-Group list
- new rx_group_delete(int rxId) method in Opd_prescription controller
- deletes linked medicines first (opd_prescrption_prescribed_template), then group row
- POST route: Opd_prescription/rx_group_delete/(:num)
- Delete button (red) added to each row in Rx-Group list table
- confirm dialog before delete (shows group name)
- reloads list after delete; clears form if deleted group was loaded
2026-03-31 04:28:18 +05:30
ad24857720 feat: align consult Rx medicine controls with Rx-Group Add/Edit masters
- consult form medicine Dose/When/Freq changed to dropdowns from dose masters
- added Where dropdown in consult medicine editor and table display
- consult now loads options from Opd_prescription/rx_group_dose_masters
- medicine add/update payload now includes dosage_where
- medicine list now returns dosage_where_label for readable table output
- edit mode supports existing values not present in current master set
- quick chips now map into select options (with safe fallback)
2026-03-31 03:31:26 +05:30
bfd155510a fix: diagnose and reduce STT 400 errors
- sttProxy now returns detailed upload error info (code, error string, php limits)
- sttProxy accepts fallback upload field name 'file' in addition to 'audio'
- reject empty audio payloads with explicit message
- client: guard against very short/empty blobs before POST to /stt-proxy
2026-03-30 19:12:49 +05:30
311a7bce4b fix: mixed-content block for STT on HTTPS - add server-side proxy
Production runs HTTPS; browser blocks http://139.59.13.39:8000 (mixed content).
Solution: CI4 proxy endpoints forward audio/health check server-side (HTTP→HTTP).

- Home::sttProxy()       POST stt-proxy    - forwards audio to STT server
- Home::sttProxyHealth() GET  stt-proxy/health - pings STT and returns {ok:bool}
- JS: auto-detect window.location.protocol; use proxy URLs on HTTPS,
  direct IP URLs on HTTP (local/dev)
- checkComplaintsSttServer: parse {ok:bool} from proxy health response
2026-03-30 19:03:20 +05:30
17e2d8e16b feat: OPD speech-to-text mic, medicine label enhancements & template search
- Add complaints Speech-to-Text (browser + server STT fallback) with interim preview
- Add Medical Mic (server STT) for examination, diagnosis, provisional diagnosis fields
- Add speech-test route + Home::speechTest() view for STT testing
- OPD prescription: resolve dosage/when/frequency labels from lookup tables
- OPD prescription: show generic/salt name below medicine name in print
- OPD prescription: translate complaints/diagnosis/advice/investigation to Hindi for patient
- Add translateToLocalPatientText() helper with English->Hindi medical term map
- Add 'Remove All' medicines button (btn_clear_medicine)
- Add template search box in Load Template modal
- Fix investigation batch add: dedup + guard against concurrent add
- Fix single investigation add: check duplicate before adding
- Fix rx status text overflow: ellipsis + title tooltip
- Remove unused FHIR History and Back to Invoice buttons from Rx header
- .gitignore: exclude public/uploads/* and writable/ayushman/*
2026-03-30 18:46:33 +05:30
d293c261e6 Add configurable footer version setting 2026-03-27 13:38:56 +05:30
b1ba3105c0 Fix AI medicine enrichment fallback and DataTable reinit issues 2026-03-27 04:16:22 +05:30
911e7b50a7 Add Ayushman package import, billing claim sheet, and reporting dashboards 2026-03-26 15:42:40 +05:30
99ec71677a Restore legacy HMS flows and add IPD document master templates 2026-03-24 04:24:19 +05:30
7ee67ff537 Fix collection total query for ONLY_FULL_GROUP_BY 2026-03-22 04:07:16 +05:30
50e2a4f145 Enhance report actions with grouped controls and PDF exports 2026-03-22 04:01:06 +05:30
a519525fa3 Fix diagnosis report query for ONLY_FULL_GROUP_BY 2026-03-22 01:16:24 +05:30
38093da3b9 Implement IPD admission/discharge editing, bill PDF modes, and invoice list view action 2026-03-21 15:47:18 +05:30
addef91468 Fix legacy billing prints and pathology template compatibility 2026-03-21 02:23:31 +05:30
300ec0e5cf feat: migrate OPD template flow to DB and apply related updates 2026-03-20 18:11:17 +05:30
145f9fba69 fix: harden hospital logo upload handling 2026-03-19 20:32:48 +05:30
47d7db6d8b refactor: remove Gemini integration and seed leakage paths
- Remove Gemini runtime fallback from OPD AI text generation and complaint drafting
- Remove legacy Gemini scan extraction path
- Update UI/provider labels to Azure/AI generic naming
- Make AI usage guardrail metrics provider-neutral (ai_today)
- Add seed export sanitization to exclude sensitive hospital_setting and audit entries
- Remove Gemini API audit entry from master seed JSON
2026-03-18 06:18:52 +05:30
4adc6d79d9 fix: redact Gemini key; exclude audit/log tables from seed exporter
- Redact AIzaSy Gemini key from clinical_audit_trail entries in seed JSON
- Add default never-export denylist to exportMasterSeedData() so that
  clinical_audit_trail, lab_log, bridge_sync_queue and session tables are
  always skipped when setup.seed.export_tables is not configured.
  This prevents API keys set via the admin UI from leaking into git via
  the audit trail even after being deleted from hospital_setting.
2026-03-18 06:13:30 +05:30
1856d990eb fix: add city_auto_u migration and fix HospitalProfile upload mkdir error
- Add migration 2026-03-18-000028_CreateCityAutoUTable.php to create
  the missing city_auto_u table (city, district, state columns) used
  by PatientModel::getCitySuggestions() — resolves 500 on /billing/patient/city

- Fix HospitalProfile::save() to check directory creation success before
  moving uploaded logo files; returns clean JSON error instead of
  throwing HTTPException when public/assets/images/ is not writable
2026-03-18 06:01:01 +05:30
1e2a86708f Fix seed export blank output with case-insensitive table resolution and fallback export 2026-03-18 05:12:20 +05:30
ee3193ce43 Add master seed data export and auto-apply during setup install - idempotent REPLACE mode prevents duplicates 2026-03-18 04:41:51 +05:30
67fbc68c1c Prioritize parent tables and remove restrictive sync table cap 2026-03-18 03:19:50 +05:30
31e7c21dd4 Order schema create statements by FK dependencies 2026-03-18 03:12:55 +05:30
47b957bf18 Handle referenced-table FK errors by creating tables without FK fallback 2026-03-18 03:08:22 +05:30
b9dc1afe4b Fix schema sync FK dependency ordering with retry passes 2026-03-18 03:06:22 +05:30