Skip to content

feat(clinical): favourite diagnosis API — weight range support, no-filter fallbacks, and channel report summaries#21453

Merged
buddhika75 merged 9 commits into
developmentfrom
21452-favourite-diagnosis-api
Jun 13, 2026
Merged

feat(clinical): favourite diagnosis API — weight range support, no-filter fallbacks, and channel report summaries#21453
buddhika75 merged 9 commits into
developmentfrom
21452-favourite-diagnosis-api

Conversation

@buddhika75

@buddhika75 buddhika75 commented Jun 13, 2026

Copy link
Copy Markdown
Member

Summary

Completes the favourite diagnosis/medicine API work described in #21452, adding weight range support to the API, no-filter fallbacks for clinical workflows when patient age/weight aren't recorded, channel report cashier summaries, a new pharmacy privilege, and several clinical workflow fixes.

Changes

Favourite Medicine/Diagnosis API

  • Weight range support: FavouriteMedicineApiService now accepts fromKg/toKg fields; age range is made optional when weight range is provided
  • API response: FavouriteMedicineApi serializes fromKg/toKg in JSON responses

Clinical Workflow (OPD Visit)

  • No-filter fallbacks: PatientEncounterController adds a method 4 fallback that loads favourite configurations even when patient DOB/weight aren't recorded, so doctors still get suggestions
  • FavouriteDiagnosis direct fallback: when no separate FavouriteMedicine config exists for a diagnosis-recommended medicine, the FavouriteDiagnosis template's own dose/frequency/duration is used directly
  • Add Favourite validation: a medicine must be selected before clicking 'Add Favourite'
  • Legacy prescription type detection: both PatientEncounterController and PastPatientEncounterController now detect prescriptions saved with legacy null or VisitDocument type by checking DocumentTemplateType.Prescription; new prescriptions default to VisitPrescription

Prescription → Pharmacy

  • Rich text separation: PracticeBookingController now sets prescriptionHtml (rich Quill HTML) and converts it to plain text for the bill comment via htmlToPlainText()
  • Prescription preview panel: pharmacy_bill_retail_sale.xhtml shows a toggleable panel rendering the prescription HTML
  • Stale data cleanup: prescription data is cleared when switching to an encounter with no prescriptions

Channel Reports

  • Cashier-based summaries: ChannelReportTempController adds fetchBillsTotal, fetchBillsTotalSessoin, fetchCashiers, fetchUserRows, fetchDateRangeRows with WebUser/agency support

Pharmacy Administration

  • New privilege: PharmacyItemNameEdit — registered in Privileges enum, getCategory(), and UserPrivilageController tree; gates Add/Edit/Save on VMP/VTM/ATM admin pages
  • VMP fallback lookup: PharmacyBean falls back to direct VMP.VTM_ID when VirtualProductIngredient join table is unpopulated

Closes #21452

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Channel reporting can group appointment/count summaries by cashier or by date.
    • Retail pharmacy can auto-populate bills from OPD prescriptions with FEFO stock selection.
    • Prescription preview added to pharmacy billing UI.
    • API support for searching clinical diagnoses and distinguishing favourite-diagnosis templates.
  • Improvements

    • Clinical queue UI reorganized with improved filtering and tabbed layout.
    • Medicine suggestion/prescription logic gains robust fallback resolution and legacy-prescription handling.
    • Pharmacy bill text now converts rich prescription HTML to readable plain text.
  • Security

    • New privilege to control pharmacy item name editing.

buddhika75 and others added 6 commits June 12, 2026 21:33
…from clinical queue

When an OPD prescription is written in Prescriptions Given on the EMR
visit page (emr/opd_visit.xhtml) and the user clicks Pharmacy Bill on
the clinical queue (clinical/clinical_queue.xhtml), the prescribed
medicines now load automatically onto the retail sale bill - matching
the inward flow where admission prescriptions are converted to pharmacy
dispensing notes.

Root cause: PracticeBookingController.issuePharmacyBill() loaded the
encounter medicines and iterated them with an empty loop body - the
conversion to bill items was never implemented. Only the patient,
referring doctor and prescription text (as a comment) reached the
retail sale page.

Changes:
- PharmacySaleController.addBillItemsFromEncounterMedicines(): converts
  each VisitMedicine prescription to a bill item. Resolves dispensable
  item and quantity via PrescriptionToItemService (qty defaults to 1
  when the prescription is incomplete so the pharmacist adjusts it on
  the page), auto-picks an earliest-expiry (FEFO) in-date stock batch
  from the logged-in user's department, resolving VMP/VTM prescriptions
  to candidate AMPs via PharmacyBean.resolveAmps().
- Items are added through the existing addBillItemSingleItem() so all
  retail-sale safeguards apply unchanged: expiry check, stock quantity
  check, duplicate batch check, UserStock locking and allergy check.
- Dose, frequency, duration and comment are carried onto the bill
  item's prescription so bill descriptions and drug label printing work
  as in the inward discharge issue flow.
- Medicines that cannot be auto-added (no stock, conversion failure,
  duplicate batch) are reported in a visible warning, never silently
  dropped.
- PracticeBookingController.issuePharmacyBill(): replaced the empty
  placeholder loop with a call to the new conversion method.

Mirrors PharmacySaleBhtController.prepareDischargeIssueFromPrescriptions
(issue #21334) for the OPD retail sale path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ility

Rework clinical/clinical_queue.xhtml to follow the project UI and
accessibility-first guidelines:

- Replace the h:panelGrid filter layout with a responsive Bootstrap
  row/col grid; labels bound to inputs via p:outputLabel for=...
- Add stable ids to every actionable control (btnProcess, btnVisit,
  btnMarkPresent, btnMarkAbsent, btnEditVisit, btnViewVisit,
  btnOpdBill, btnPharmacyBill) and descriptive title attributes that
  include the patient name and queue number, so Playwright/automation
  can target individual rows.
- Cap both speciality and doctor autocompletes with maxResults="20"
  and add placeholders.
- Date/doctor filter changes now re-render the whole queue form
  (render=":queueForm") instead of a single resolved component id.
- DataTables: add widgetVar and rowKey, pagination (25 rows, bottom,
  hidden when not needed), emptyMessage texts, and a row highlight for
  absent patients in the To Complete tab.
- To Complete tab gains Age, Phone and a Waiting/Absent status badge
  column; both tab titles show live session counts.
- Consistent icon set and button styling (success/info/danger/warning
  variants) across row actions; growl shows message details.

JSF-only change - no Java modifications.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o favourite medicines API

- Add GET /clinical/favourite_medicines/entities/diagnoses to search
  ClinicalEntity records (Disease_or_Syndrome) for use as forItemName
- Support type=FavouriteMedicine (default) / type=FavouriteDiagnosis on
  create, search, and by-id endpoints
- Resolve forItemName to a diagnosis for FavouriteDiagnosis templates,
  with "did you mean" suggestions on mismatch
- Register the new endpoint and capability in CapabilityStatementResource
  and the AI chat module listing

Closes #21452
…ourite diagnosis/medicine, and channel report cashier summaries

- FavouriteMedicineApiService: add fromKg/toKg weight range fields to templates;
  make age range optional when weight range is provided; validate weight ranges
- PatientEncounterController: add method 4 (no age/weight filter) fallback so
  favourites load even when patient DOB/weight aren't recorded; validate a
  medicine is selected before 'Add Favourite'; fall back to FavouriteDiagnosis
  template directly when no separate FavouriteMedicine config exists
- PastPatientEncounterController: detect legacy prescriptions persisted with
  null or VisitDocument type via DocumentTemplateType.Prescription, default
  new prescriptions to VisitPrescription type
- PracticeBookingController: separate prescriptionHtml (rich text) from plain
  comment via htmlToPlainText(); clear stale prescription when switching
  encounters
- ChannelReportTempController: add fetchBillsTotal, fetchCashiers,
  fetchUserRows, fetchDateRangeRows with WebUser/agency support for
  cashier-based channel reporting
- FavouriteMedicineApi: serialize fromKg/toKg in API responses
- PharmacyBean: fallback VMP lookup via direct VMP.VTM_ID when
  VirtualProductIngredient join table is unpopulated
- Privileges/UserPrivilageController: add PharmacyItemNameEdit privilege
- pharmacy_bill_retail_sale.xhtml: add toggleable prescription preview panel
  rendering prescriptionHtml
- lab_vmp/vtm, store_atm/vtm XHTML: gate Add/Edit/Save buttons behind
  PharmacyItemNameEdit privilege
- opd_visit.xhtml: process acMedicine + dose/frequency/duration fields when
  adding a favourite, so the current selection is captured

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@buddhika75, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 1 minute and 57 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c4120378-0153-479f-8ed3-dba1c2851530

📥 Commits

Reviewing files that changed from the base of the PR and between 192c3b1 and 9e4fa86.

📒 Files selected for processing (1)
  • src/main/webapp/clinical/clinical_queue.xhtml

Walkthrough

This PR extends the clinical and pharmacy subsystems with three major themes: adding FavouriteDiagnosis API support for diagnosis-driven medicine recommendations, standardizing prescription typing and integrating encounter medicines into pharmacy retail sales, introducing a new pharmacy edit privilege with UI enforcement, and restructuring the clinical queue UI with paginated tables and improved filtering.

Changes

FavouriteDiagnosis API and Type-Aware Template Management

Layer / File(s) Summary
Type field and documentation in request DTO
src/main/java/com/divudi/core/data/dto/clinical/FavouriteMedicineCreateRequestDTO.java
Adds type field to request DTO with getters/setters and updates forItemName docs to clarify conditional requirements based on type (FavouriteMedicine vs FavouriteDiagnosis).
Service layer diagnosis integration and type parsing
src/main/java/com/divudi/service/clinical/FavouriteMedicineApiService.java
Wires ClinicalEntityFacade dependency, parses type field, validates age/weight ranges with clear error messages, constructs templates with forItem diagnosis resolution via ClinicalEntity lookup, and adds generalized order-number computation by template type.
Type-parameterized search, dual-type retrieval, and weight updates
src/main/java/com/divudi/service/clinical/FavouriteMedicineApiService.java
Updates search to filter by optional type (defaulting to FavouriteMedicine), allows fetching either medicine or diagnosis by ID via type IN predicate, implements weight range validation (fromKg < toKg), and provides diagnosis lookup helpers with SymanticType.Disease_or_Syndrome filtering.
Diagnoses endpoint and template response extensions
src/main/java/com/divudi/ws/clinical/FavouriteMedicineApi.java
Adds GET /clinical/favourite_medicines/entities/diagnoses endpoint for diagnosis search, extends template response mapping to include type, weight ranges (fromKg/toKg), and forItemId alongside name.
Type parameter support in search criteria
src/main/java/com/divudi/ws/clinical/FavouriteMedicineApi.java
Updates search parameter parsing to accept optional type filter and include it in search criteria map.
System prompt and capability statement updates
src/main/java/com/divudi/service/AnthropicApiService.java, src/main/java/com/divudi/ws/common/CapabilityStatementResource.java
Clarifies FavouriteDiagnosis forItem resolution via diagnoses endpoint in system prompt and adds diagnosis search path and type handling details to capability statement.

Prescription Typing Standardization and Encounter Favorite Selection

Layer / File(s) Summary
VisitPrescription assignment and null backfill
src/main/java/com/divudi/bean/clinical/PastPatientEncounterController.java, src/main/java/com/divudi/bean/clinical/PatientEncounterController.java
Sets ClinicalFindingValue.VisitPrescription when generating default prescription documents and backfills null types to VisitPrescription during prescription updates across both encounter controllers.
Legacy-compatible prescription retrieval
src/main/java/com/divudi/bean/clinical/PastPatientEncounterController.java, src/main/java/com/divudi/bean/clinical/PatientEncounterController.java
Rewrites fillEncounterPrescreptions to include current VisitPrescription entries and legacy records with null or VisitDocument types when their DocumentTemplate has type Prescription.
Favourite medicine/diagnosis selection with extended fallbacks
src/main/java/com/divudi/bean/clinical/PatientEncounterController.java
Extends addFavouriteMedicines to derive selected medicine from autocomplete with no-age/weight fallback lookup, expands addFavouriteDiagnosis with explicit no-age/weight restriction path, per-medicine unrestricted configuration fallback, and fallback to FavouriteDiagnosis template when configuration missing.

Pharmacy Encounter Billing from Prescriptions

Layer / File(s) Summary
Prescription state reset and HTML handoff
src/main/java/com/divudi/bean/clinical/PracticeBookingController.java
Clears stale encounterPrescreption before processing new encounter, sets prescriptionHtml on pharmacy bill, converts prescription to plain-text comment via new htmlToPlainText helper, and passes filled encounter medicines for auto-add.
Encounter medicine auto-add with FEFO stock and prescription display
src/main/java/com/divudi/bean/pharmacy/PharmacySaleController.java, src/main/java/com/divudi/ejb/PharmacyBean.java, src/main/webapp/pharmacy/pharmacy_bill_retail_sale.xhtml
Adds PrescriptionToItemService dependency, implements addBillItemsFromEncounterMedicines with FEFO stock batch selection (including AMP lookup fallback and earliest-expiry in-date filtering by department), manages prescriptionHtml state lifecycle, clears it on bill reset, and renders prescription preview panel in retail sale UI.
OPD visit favourite button processing extension
src/main/webapp/emr/opd_visit.xhtml
Updates Add Favourite button to process medicine selection and dose/frequency/duration inputs in addition to button itself.

PharmacyItemNameEdit Privilege Enforcement

Layer / File(s) Summary
Privilege constant and tree node registration
src/main/java/com/divudi/core/data/Privileges.java, src/main/java/com/divudi/bean/common/UserPrivilageController.java
Adds PharmacyItemNameEdit enum constant, maps it to Pharmacy category, and registers it in the privilege tree under Pharmacy.
Privilege-gated button conditions on pharmacy admin pages
src/main/webapp/pharmacy/admin/lab_vmp.xhtml, src/main/webapp/pharmacy/admin/lab_vtm.xhtml, src/main/webapp/pharmacy/admin/store_atm.xhtml, src/main/webapp/pharmacy/admin/store_vtm.xhtml
Adds PharmacyItemNameEdit privilege checks to Add New, Edit, and Save button disabled conditions across all pharmacy admin pages.

Clinical Queue Page Restructure and Table Rebuild

Layer / File(s) Summary
Filter form and panel restructure
src/main/webapp/clinical/clinical_queue.xhtml
Replaces grid-based filter UI with explicit header facet, dedicated Bootstrap-layout filter form, updated calendar and autocomplete with new AJAX wiring, and repositioned Process button.
To Complete and Completed table pagination and action redesign
src/main/webapp/clinical/clinical_queue.xhtml
Rebuilds both queue tabs with tabView/dataTable pagination (rows=25), introduces Status column (Absent vs Waiting), consolidates patient actions into Actions column with conditional rendering, adds View Visit encounter navigation, and updates button wiring and enable/disable logic.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant FavouriteMedicineApi
  participant FavouriteMedicineService
  participant ClinicalEntityFacade
  participant DiagnosisRepository
  Client->>FavouriteMedicineApi: GET /favourite_medicines/entities/diagnoses?query=URTI
  FavouriteMedicineApi->>FavouriteMedicineService: searchDiagnoses(query)
  FavouriteMedicineService->>ClinicalEntityFacade: findByNameLike(query, SymanticType.Disease_or_Syndrome)
  ClinicalEntityFacade->>DiagnosisRepository: JPQL disease_or_syndrome filtered query
  DiagnosisRepository-->>ClinicalEntityFacade: List<ClinicalEntity> diagnoses
  ClinicalEntityFacade-->>FavouriteMedicineService: matched diagnosis records
  FavouriteMedicineService-->>FavouriteMedicineApi: List<ClinicalEntity>
  FavouriteMedicineApi-->>Client: JSON response with type=FavouriteDiagnosis, forItem=diagnosis
Loading
sequenceDiagram
  participant PatientEncounter
  participant PracticeBooking
  participant PharmacySale
  participant PrescriptionToItemService
  participant PharmacyBean
  PatientEncounter->>PatientEncounter: fillEncounterPrescreptions()
  PatientEncounter-->>PatientEncounter: List of VisitPrescription + legacy
  PracticeBooking->>PracticeBooking: issuePharmacyBill(opdVisit)
  PracticeBooking->>PharmacySale: prescriptionHtml = HTML
  PracticeBooking->>PharmacySale: addBillItemsFromEncounterMedicines(medicines)
  PharmacySale->>PrescriptionToItemService: convert each medicine
  PrescriptionToItemService-->>PharmacySale: conversion results
  PharmacySale->>PharmacyBean: resolveAmps(item)
  PharmacyBean-->>PharmacySale: list of dispensable items
  PharmacySale->>PharmacySale: findFefoStockForPrescribedItem()
  PharmacySale->>PharmacySale: addBillItemSingleItem() per item
  PharmacySale-->>PharmacySale: retail sale bill ready with medicines+prescription
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: favourite diagnosis API enhancements (weight range support, no-filter fallbacks) and channel report summaries, which are core themes throughout the changeset.
Linked Issues check ✅ Passed All coding requirements from #21452 are met: diagnosis search endpoint [FavouriteMedicineApi], forItemName resolution [FavouriteMedicineApiService], FavouriteDiagnosis creation support [FavouriteMedicineApiService], and API documentation updates [CapabilityStatementResource, AnthropicApiService].
Out of Scope Changes check ✅ Passed All changes relate directly to issue #21452 objectives: favourite medicine/diagnosis API support, clinical workflow enhancements, prescription-to-pharmacy integration, channel reporting, and pharmacy administration gating.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 21452-favourite-diagnosis-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

PR validation failed because local JNDI names (jdbc/coop, jdbc/rhAuditDS)
were committed in the branch history instead of the CI/CD placeholders
(${JDBC_DATASOURCE}, ${JDBC_AUDIT_DATASOURCE}).

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f7b6ddaf3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/resources/META-INF/persistence.xml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/java/com/divudi/service/clinical/FavouriteMedicineApiService.java (1)

233-235: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve IllegalArgumentException instead of wrapping everything as RuntimeException.

These catch blocks convert new request-validation failures (invalid type, age/weight ranges, etc.) into 500 errors, which breaks client error semantics.

Proposed fix
-        } catch (Exception e) {
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (Exception e) {
             throw new RuntimeException("Failed to create favourite medicine: " + e.getMessage(), e);
         }
-        } catch (Exception e) {
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (Exception e) {
             throw new RuntimeException("Failed to search favourite medicines: " + e.getMessage(), e);
         }
-        } catch (Exception e) {
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (Exception e) {
             throw new RuntimeException("Failed to update favourite medicine: " + e.getMessage(), e);
         }

Also applies to: 357-359, 455-457

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/divudi/service/clinical/FavouriteMedicineApiService.java`
around lines 233 - 235, The catch blocks in FavouriteMedicineApiService that
currently do "catch (Exception e) { throw new RuntimeException(..., e); }" (seen
around the create/update/delete flows at the three occurrences) are converting
client validation failures like IllegalArgumentException into 500s; update each
of those catch sites to preserve IllegalArgumentException by rethrowing it
unchanged (or throw it as-is) and only wrap/translate other unexpected
Exceptions into RuntimeException (or an appropriate server error). Locate the
catch blocks in the FavouriteMedicineApiService class (the create/update/delete
handlers around the reported spots) and replace the single broad catch with a
two-branch handling: catch IllegalArgumentException and rethrow, then catch
Exception and wrap as before.
src/main/java/com/divudi/ws/clinical/FavouriteMedicineApi.java (1)

110-134: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Return 400 for invalid search type instead of 500.

Now that type is accepted in query params, invalid values should be treated as client input errors. The current handler maps them to 500.

Proposed fix
     public Response searchFavouriteMedicines() {
         try {
@@
             return successResponse(responseData);
 
+        } catch (IllegalArgumentException e) {
+            return errorResponse("Invalid request: " + e.getMessage(), 400);
         } catch (Exception e) {
             return errorResponse("An error occurred: " + e.getMessage(), 500);
         }
     }

Also applies to: 1008-1012

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/divudi/ws/clinical/FavouriteMedicineApi.java` around lines
110 - 134, The handler searchFavouriteMedicines currently maps invalid query
'type' values to a 500; validate the 'type' earlier (in parseSearchParams or
immediately after it) and return a 400 Bad Request when the value is
unknown/invalid. Concretely, update parseSearchParams (or add a small validation
in searchFavouriteMedicines) to detect invalid 'type' and throw an
IllegalArgumentException or return a validation error, then catch that specific
exception (or check the validation result) and call errorResponse(..., 400)
instead of letting it propagate to the generic 500 handler; apply the same
change to the other similar handler mentioned (the block around lines 1008-1012)
so invalid client input consistently returns 400.
🧹 Nitpick comments (2)
src/main/java/com/divudi/bean/channel/ChannelReportTempController.java (1)

448-479: ⚖️ Poor tradeoff

Consider batching queries to reduce database round-trips.

This method executes 9 database queries per cashier (3 bill-type counts + 6 sum queries). For reports with many cashiers, this compounds quickly (e.g., 10 cashiers = 90 queries). A single aggregate query with GROUP BY could fetch all metrics in one round-trip.

This is acceptable for small user counts but may become a bottleneck at scale.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/divudi/bean/channel/ChannelReportTempController.java`
around lines 448 - 479, fetchUserRows currently calls fetchBillsTotal repeatedly
per cashier (inside fetchUserRows and via fetchCashiers), causing N*9 DB
queries; replace this with a single aggregated query: add a new DAO/service
method (e.g., fetchAggregatedBillMetrics or fetchBillMetricsByUser) that accepts
the same filters (fDate, tDate, bts, bill type distinctions and flags used in
fetchBillsTotal) and returns per-WebUser aggregates (billCount, canceledCount,
refundCount, netTotal, hosTotal) in one GROUP BY webUser result (or a
Map<WebUser, Metrics>); then modify fetchUserRows to call that new method once,
iterate the returned aggregates to build ChannelSummeryUserRow objects, set
totals (tbc, tcc, trc, tht, tst) and only call fetchCashiers to preserve
order/filtering if needed—this reduces DB round-trips by consolidating the 9
per-user fetchBillsTotal calls into a single grouped query.
src/main/java/com/divudi/bean/clinical/PatientEncounterController.java (1)

1511-1512: ⚡ Quick win

Remove debug System.out.println statements before merging.

The method contains numerous debug statements (approximately 40+) throughout addFavouriteDiagnosis(). These should be removed or converted to proper logging at an appropriate level (e.g., FINE or DEBUG) before production.

Example locations to clean up

Lines containing System.out.println("DEBUG: ...) throughout the method body (1511-1778).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/divudi/bean/clinical/PatientEncounterController.java`
around lines 1511 - 1512, The method addFavouriteDiagnosis() contains many
System.out.println debug statements (e.g., those printing patient and
selectedDiagnosis) that must be removed before merging; replace them with proper
logger calls (use the existing logger instance or create a private static final
Logger) at an appropriate level (FINE/DEBUG) or delete them entirely, ensuring
you update all occurrences inside addFavouriteDiagnosis() and any helper methods
referenced there so no System.out.println calls remain and contextual info uses
logger.debug/logger.fine with patient.getPerson().getNameWithTitle(),
selectedDiagnosis.getName(), and other referenced variables.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/com/divudi/bean/channel/ChannelReportTempController.java`:
- Around line 251-259: Check for null on the Bill variable b before calling
b.getClass() (move the null-guard to the top of the method or before these class
checks) and replace the direct getClass() comparisons with safer instanceof
checks for BilledBill, CancelledBill, and RefundBill; additionally ensure you
always append a date filter to the sql by adding a fallback date clause (e.g.,
"and b.createdAt between :fromDate and :toDate") when none of the specific
bill-type conditions match so the query cannot return unbounded results.

In `@src/main/java/com/divudi/bean/clinical/PracticeBookingController.java`:
- Around line 387-391: The PharmacySaleController is session-scoped and its
preBill must be cleared before auto-loading a new encounter; update
PracticeBookingController so that after obtaining the PharmacySaleController
(via getPharmacySaleController()) and before seeding patient/prescription/bill
items (i.e. before calling addBillItemsFromEncounterMedicines), call the
controller's resetAll() or clearBill() method to clear previous draft state
(preBill, comments, payments, and stock locks), then proceed to
addBillItemsFromEncounterMedicines(encounterMedicines).

In `@src/main/java/com/divudi/bean/pharmacy/PharmacySaleController.java`:
- Around line 1877-1892: The code currently defaults to requiredQty=1 when
calculateItemAndQuantity fails or throws; instead, mirror the discharge
conversion flow by treating failed or exceptional conversions as "skip
conversion" and do not auto-add a qty=1. Specifically, in the block that calls
prescriptionToItemService.calculateItemAndQuantity(sourcePrescription) (and
handles PrescriptionToItemService.PrescriptionToItemResult), only set
dispensableItem and calculatedQty when result != null && result.isSuccess(); if
result is null, !isSuccess(), or an exception occurs, clear/leave
dispensableItem null (or set a flag) and avoid computing requiredQty = 1.0 so
downstream logic that relies on dispensableItem/requiredQty will skip adding the
item instead of billing one unit.

In `@src/main/webapp/clinical/clinical_queue.xhtml`:
- Around line 231-234: Replace the stale global encounter binding and bind the
pharmacy patient from the selected row object instead: change the second
<f:setPropertyActionListener> that currently sets
target="#{pharmacySaleController.patient}" with
value="#{practiceBookingController.opdVisit.patient}" to use the row variable
(bsc) patient (e.g. value="#{bsc.patient}") so pharmacySaleController.patient is
populated from the clicked row rather than
practiceBookingController.opdVisit.patient.
- Around line 21-78: The form filterForm allows Enter to submit unintentionally;
guard it by adding a key handler on the <h:form id="filterForm"> to prevent
default when Enter is pressed (e.g., onkeydown checking event.key === 'Enter' or
keyCode === 13 and calling event.preventDefault()), leaving the Process button
(btnProcess) as the explicit submit trigger and keeping existing listeners
(practiceBookingController.listCompleteAndToCompleteBillSessions) and
autocomplete/calendar components (calSessionDate, acSpeciality, acStaff)
unchanged.
- Around line 212-235: The OPD and Pharmacy bill buttons (p:commandButton
id="btnOpdBill" calling practiceBookingController.issueServices() and
id="btnPharmacyBill" calling practiceBookingController.issuePharmacyBill() /
actionListener pharmacySaleController.resetAll()) lack double-submit protection;
add a client-side JavaScript confirm prompt to both buttons (e.g., onclick that
returns confirm(...)) to require explicit user confirmation before submission,
and implement a server-side re-entrancy guard inside the target methods
(practiceBookingController.issueServices and
practiceBookingController.issuePharmacyBill) that checks and sets a short-lived
in-memory or DB flag on billSession (or the underlying booking/bill entity) to
ignore duplicate requests if already processing/completed; ensure the
f:setPropertyActionListener usages for billSession and
pharmacySaleController.patient remain but only proceed when the server-side
guard permits execution.

In `@src/main/webapp/pharmacy/pharmacy_bill_retail_sale.xhtml`:
- Line 958: The view currently renders unescaped HTML via h:outputText
value="#{pharmacySaleController.prescriptionHtml}" escape="false", which allows
XSS; change the page to render only a sanitized/allowlisted HTML property (e.g.,
prescriptionHtmlSafe) or re-enable escaping (escape="true") and move
sanitization into the controller; in PharmacySaleController add a getter that
returns a sanitized version of prescriptionHtml using a trusted sanitizer (OWASP
HTML Sanitizer or a strict allowlist), expose that sanitized property to the
view and replace escape="false" with the safe property (or keep escape enabled)
so only cleaned markup is rendered.

---

Outside diff comments:
In `@src/main/java/com/divudi/service/clinical/FavouriteMedicineApiService.java`:
- Around line 233-235: The catch blocks in FavouriteMedicineApiService that
currently do "catch (Exception e) { throw new RuntimeException(..., e); }" (seen
around the create/update/delete flows at the three occurrences) are converting
client validation failures like IllegalArgumentException into 500s; update each
of those catch sites to preserve IllegalArgumentException by rethrowing it
unchanged (or throw it as-is) and only wrap/translate other unexpected
Exceptions into RuntimeException (or an appropriate server error). Locate the
catch blocks in the FavouriteMedicineApiService class (the create/update/delete
handlers around the reported spots) and replace the single broad catch with a
two-branch handling: catch IllegalArgumentException and rethrow, then catch
Exception and wrap as before.

In `@src/main/java/com/divudi/ws/clinical/FavouriteMedicineApi.java`:
- Around line 110-134: The handler searchFavouriteMedicines currently maps
invalid query 'type' values to a 500; validate the 'type' earlier (in
parseSearchParams or immediately after it) and return a 400 Bad Request when the
value is unknown/invalid. Concretely, update parseSearchParams (or add a small
validation in searchFavouriteMedicines) to detect invalid 'type' and throw an
IllegalArgumentException or return a validation error, then catch that specific
exception (or check the validation result) and call errorResponse(..., 400)
instead of letting it propagate to the generic 500 handler; apply the same
change to the other similar handler mentioned (the block around lines 1008-1012)
so invalid client input consistently returns 400.

---

Nitpick comments:
In `@src/main/java/com/divudi/bean/channel/ChannelReportTempController.java`:
- Around line 448-479: fetchUserRows currently calls fetchBillsTotal repeatedly
per cashier (inside fetchUserRows and via fetchCashiers), causing N*9 DB
queries; replace this with a single aggregated query: add a new DAO/service
method (e.g., fetchAggregatedBillMetrics or fetchBillMetricsByUser) that accepts
the same filters (fDate, tDate, bts, bill type distinctions and flags used in
fetchBillsTotal) and returns per-WebUser aggregates (billCount, canceledCount,
refundCount, netTotal, hosTotal) in one GROUP BY webUser result (or a
Map<WebUser, Metrics>); then modify fetchUserRows to call that new method once,
iterate the returned aggregates to build ChannelSummeryUserRow objects, set
totals (tbc, tcc, trc, tht, tst) and only call fetchCashiers to preserve
order/filtering if needed—this reduces DB round-trips by consolidating the 9
per-user fetchBillsTotal calls into a single grouped query.

In `@src/main/java/com/divudi/bean/clinical/PatientEncounterController.java`:
- Around line 1511-1512: The method addFavouriteDiagnosis() contains many
System.out.println debug statements (e.g., those printing patient and
selectedDiagnosis) that must be removed before merging; replace them with proper
logger calls (use the existing logger instance or create a private static final
Logger) at an appropriate level (FINE/DEBUG) or delete them entirely, ensuring
you update all occurrences inside addFavouriteDiagnosis() and any helper methods
referenced there so no System.out.println calls remain and contextual info uses
logger.debug/logger.fine with patient.getPerson().getNameWithTitle(),
selectedDiagnosis.getName(), and other referenced variables.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 718eb4b1-88c2-44ad-a78b-9a73f61d694f

📥 Commits

Reviewing files that changed from the base of the PR and between 53360f7 and 7ccfb74.

📒 Files selected for processing (20)
  • src/main/java/com/divudi/bean/channel/ChannelReportTempController.java
  • src/main/java/com/divudi/bean/clinical/PastPatientEncounterController.java
  • src/main/java/com/divudi/bean/clinical/PatientEncounterController.java
  • src/main/java/com/divudi/bean/clinical/PracticeBookingController.java
  • src/main/java/com/divudi/bean/common/UserPrivilageController.java
  • src/main/java/com/divudi/bean/pharmacy/PharmacySaleController.java
  • src/main/java/com/divudi/core/data/Privileges.java
  • src/main/java/com/divudi/core/data/dto/clinical/FavouriteMedicineCreateRequestDTO.java
  • src/main/java/com/divudi/ejb/PharmacyBean.java
  • src/main/java/com/divudi/service/AnthropicApiService.java
  • src/main/java/com/divudi/service/clinical/FavouriteMedicineApiService.java
  • src/main/java/com/divudi/ws/clinical/FavouriteMedicineApi.java
  • src/main/java/com/divudi/ws/common/CapabilityStatementResource.java
  • src/main/webapp/clinical/clinical_queue.xhtml
  • src/main/webapp/emr/opd_visit.xhtml
  • src/main/webapp/pharmacy/admin/lab_vmp.xhtml
  • src/main/webapp/pharmacy/admin/lab_vtm.xhtml
  • src/main/webapp/pharmacy/admin/store_atm.xhtml
  • src/main/webapp/pharmacy/admin/store_vtm.xhtml
  • src/main/webapp/pharmacy/pharmacy_bill_retail_sale.xhtml

Comment thread src/main/java/com/divudi/bean/channel/ChannelReportTempController.java Outdated
Comment thread src/main/java/com/divudi/bean/pharmacy/PharmacySaleController.java
Comment thread src/main/webapp/clinical/clinical_queue.xhtml
Comment thread src/main/webapp/clinical/clinical_queue.xhtml
Comment thread src/main/webapp/clinical/clinical_queue.xhtml
Comment thread src/main/webapp/pharmacy/pharmacy_bill_retail_sale.xhtml
- ChannelReportTempController.java: guard b.getClass() calls at lines 251-259
  behind a null check — consistent with the existing null guard at line 280
- clinical_queue.xhtml: add onclick=this.disabled=true on btnOpdBill and
  btnPharmacyBill to prevent accidental double-issue
- clinical_queue.xhtml: bind pharmacySaleController.patient from bsc.bill.patient
  (selected row) rather than the stale practiceBookingController.opdVisit.patient

Co-Authored-By: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/webapp/clinical/clinical_queue.xhtml`:
- Line 218: Remove the client-side disabling that breaks non-AJAX JSF form
submits: locate the p:commandButton(s) using onclick="this.disabled=true;" (the
primary form submit buttons with ajax="false") and remove that onclick
attribute; instead implement double-submit prevention via a confirm() dialog on
the client or add server-side re-entrancy guard logic in the backing bean (e.g.,
a submission-in-progress flag checked/updated in the action method). Also remove
the same onclick pattern on the other occurrence noted (the second button
instance) so the button name/value is preserved on POST.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7200585d-22f6-445e-ad62-95622d83f86b

📥 Commits

Reviewing files that changed from the base of the PR and between 7ccfb74 and 192c3b1.

📒 Files selected for processing (2)
  • src/main/java/com/divudi/bean/channel/ChannelReportTempController.java
  • src/main/webapp/clinical/clinical_queue.xhtml
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/divudi/bean/channel/ChannelReportTempController.java

Comment thread src/main/webapp/clinical/clinical_queue.xhtml Outdated
…m guard

Replace `onclick="this.disabled=true;"` on btnOpdBill and btnPharmacyBill
with `onclick="if (!confirm('…')) return false;"` per the codebase UI
guidelines (developer_docs/ui/comprehensive-ui-guidelines.md §358–363).

Disabling the button synchronously in onclick before the form POST fires
excludes the button's name/value from the request, potentially breaking
JSF action dispatch on ajax=false PrimeFaces command buttons.

Co-Authored-By: Claude <noreply@anthropic.com>
@buddhika75 buddhika75 merged commit 2c86f35 into development Jun 13, 2026
3 checks passed
@buddhika75 buddhika75 deleted the 21452-favourite-diagnosis-api branch June 13, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FavouriteMedicineApi: add diagnosis search and FavouriteDiagnosis creation endpoints

1 participant