Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
747 changes: 747 additions & 0 deletions src/main/java/com/divudi/bean/channel/ChannelReportTempController.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.divudi.core.data.BillType;
import com.divudi.core.data.SymanticType;
import com.divudi.core.data.clinical.ClinicalFindingValueType;
import com.divudi.core.data.clinical.DocumentTemplateType;
import com.divudi.core.data.clinical.PrescriptionTemplateType;
import com.divudi.core.data.inward.PatientEncounterType;
import com.divudi.core.data.lab.InvestigationResultForGraph;
Expand Down Expand Up @@ -1401,6 +1402,7 @@ public void generateDocumentsFromDocumentTemplates(PatientEncounter encounter) {
for (DocumentTemplate t : dts) {
if (t.isDefaultTemplate()) {
ClinicalFindingValue cfv = new ClinicalFindingValue();
cfv.setClinicalFindingValueType(ClinicalFindingValueType.VisitPrescription);
cfv.setEncounter(encounter);
cfv.setDocumentTemplate(t);
cfv.setStringValue(t.getName());
Expand Down Expand Up @@ -1518,6 +1520,9 @@ private void updateOrGeneratePrescription() {
}
if (encounterPrescreption != null) {
encounterPrescreption.setLobValue(generateDocumentFromTemplate(encounterPrescreption.getDocumentTemplate(), current));
if (encounterPrescreption.getClinicalFindingValueType() == null) {
encounterPrescreption.setClinicalFindingValueType(ClinicalFindingValueType.VisitPrescription);
}
if (encounterPrescreption.getId() == null) {
clinicalFindingValueFacade.create(encounterPrescreption);
} else {
Expand All @@ -1533,7 +1538,7 @@ private void updateOrGeneratePrescription() {
}
if (prescTemplate != null) {
encounterPrescreption = new ClinicalFindingValue();
encounterPrescreption.setClinicalFindingValueType(ClinicalFindingValueType.VisitDocument);
encounterPrescreption.setClinicalFindingValueType(ClinicalFindingValueType.VisitPrescription);
encounterPrescreption.setDocumentTemplate(prescTemplate);
encounterPrescreption.setEncounter(current);
encounterPrescreption.setLobValue(generateDocumentFromTemplate(prescTemplate, current));
Expand Down Expand Up @@ -2699,9 +2704,31 @@ private List<ClinicalFindingValue> fillEncounterDocuments(PatientEncounter encou
}

private List<ClinicalFindingValue> fillEncounterPrescreptions(PatientEncounter encounter) {
List<ClinicalFindingValueType> clinicalFindingValueTypes = new ArrayList<>();
clinicalFindingValueTypes.add(ClinicalFindingValueType.VisitPrescription);
return loadCurrentEncounterFindingValues(encounter, clinicalFindingValueTypes);
List<ClinicalFindingValue> vs = new ArrayList<>();
if (encounterFindingValues == null) {
encounterFindingValues = fillEncounterFindingValues(encounter);
}
if (encounterFindingValues == null) {
encounterFindingValues = new ArrayList<>();
}
for (ClinicalFindingValue v : encounterFindingValues) {
if (v == null) {
continue;
}
if (v.getClinicalFindingValueType() == ClinicalFindingValueType.VisitPrescription) {
vs.add(v);
continue;
}
// Legacy prescriptions were persisted with a null or VisitDocument type;
// recognise them through their document template type instead.
boolean legacyType = v.getClinicalFindingValueType() == null
|| v.getClinicalFindingValueType() == ClinicalFindingValueType.VisitDocument;
if (legacyType && v.getDocumentTemplate() != null
&& v.getDocumentTemplate().getType() == DocumentTemplateType.Prescription) {
vs.add(v);
}
}
return vs;
}

private List<ClinicalFindingValue> fillPlanOfAction(PatientEncounter encounter) {
Expand Down
106 changes: 94 additions & 12 deletions src/main/java/com/divudi/bean/clinical/PatientEncounterController.java
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,16 @@ public void addFavouriteMedicines(Patient patient) {
encounterMedicines = new ArrayList<>();
}

// The medicine selected via the "Medicine" autocomplete (acMedicine). Favourite
// lookups are scoped to this item so "Add Favourite" applies to the selected medicine.
Item selectedMedicine = getEncounterMedicine().getPrescription() != null
? getEncounterMedicine().getPrescription().getItem() : null;

if (selectedMedicine == null) {
JsfUtil.addErrorMessage("Please select a medicine first");
return;
}

List<PrescriptionTemplate> favouriteMedicines = new ArrayList<>();
String lookupMethod = "";

Expand All @@ -1359,7 +1369,7 @@ public void addFavouriteMedicines(Patient patient) {
// Method 2: By Patient Weight Group (if weight is available)
if (patientWeight != null && patientWeight > 0) {
favouriteMedicines = favouriteController.listFavouriteItems(
null,
selectedMedicine,
PrescriptionTemplateType.FavouriteMedicine,
patientWeight,
null
Expand All @@ -1372,7 +1382,7 @@ public void addFavouriteMedicines(Patient patient) {
// Method 3: By Patient Age Group (fallback when weight is not available or no weight-based favourites found)
if (favouriteMedicines.isEmpty() && patientAgeInDays != null && patientAgeInDays > 0) {
favouriteMedicines = favouriteController.listFavouriteItems(
null,
selectedMedicine,
PrescriptionTemplateType.FavouriteMedicine,
null,
patientAgeInDays
Expand All @@ -1382,13 +1392,27 @@ public void addFavouriteMedicines(Patient patient) {
}
}

// Method 4: No age/weight restriction — fallback when patient DOB and weight are not
// recorded so the doctor still gets the favourite configuration.
if (favouriteMedicines.isEmpty()) {
favouriteMedicines = favouriteController.listFavouriteItems(
selectedMedicine,
PrescriptionTemplateType.FavouriteMedicine,
null,
null
);
if (!favouriteMedicines.isEmpty()) {
lookupMethod = "medicine templates (no age/weight filter)";
}
}

// Check if any favourites were found
if (favouriteMedicines == null || favouriteMedicines.isEmpty()) {
String message = "No favourite medicines found";
String message = "No favourite configuration found for " + selectedMedicine.getName();
if (patientWeight != null && patientWeight > 0) {
message += " for weight " + patientWeight + " kg";
message += " at weight " + patientWeight + " kg";
} else if (patientAgeInDays != null && patientAgeInDays > 0) {
message += " for age " + (patientAgeInDays / 365) + " years";
message += " at age " + (patientAgeInDays / 365) + " years";
}
JsfUtil.addWarningMessage(message);
return;
Expand Down Expand Up @@ -1527,7 +1551,7 @@ public void addFavouriteDiagnosis() {
}

// Method 2: By Patient Age Group (fallback when weight is not available or no weight-based favourites found)
if (diagnosisMedicineList == null || diagnosisMedicineList.isEmpty() && patientAgeInDays != null && patientAgeInDays > 0) {
if ((diagnosisMedicineList == null || diagnosisMedicineList.isEmpty()) && patientAgeInDays != null && patientAgeInDays > 0) {
System.out.println("DEBUG: Step 1 - Finding medicine list by age group: " + patientAgeInDays + " days");
diagnosisMedicineList = favouriteController.listFavouriteItems(
selectedDiagnosis,
Expand All @@ -1536,11 +1560,28 @@ public void addFavouriteDiagnosis() {
patientAgeInDays
);
System.out.println("DEBUG: Age-based lookup found " + (diagnosisMedicineList != null ? diagnosisMedicineList.size() : "null") + " medicine recommendations");
if (diagnosisMedicineList!=null && !diagnosisMedicineList.isEmpty()) {
if (diagnosisMedicineList != null && !diagnosisMedicineList.isEmpty()) {
lookupMethod = "age group (" + (patientAgeInDays / 365) + " years)";
}
}

// Method 3: No age/weight restriction — used when patient weight and DOB are not
// recorded (ageInDays == null or 0). Returns all FavouriteDiagnosis templates for
// this diagnosis regardless of age range so the doctor still gets suggestions.
if (diagnosisMedicineList == null || diagnosisMedicineList.isEmpty()) {
System.out.println("DEBUG: Step 1 - No age/weight data available; fetching all templates for diagnosis");
diagnosisMedicineList = favouriteController.listFavouriteItems(
selectedDiagnosis,
PrescriptionTemplateType.FavouriteDiagnosis,
null,
null
);
System.out.println("DEBUG: Unrestricted lookup found " + (diagnosisMedicineList != null ? diagnosisMedicineList.size() : "null") + " medicine recommendations");
if (diagnosisMedicineList != null && !diagnosisMedicineList.isEmpty()) {
lookupMethod = "diagnosis templates (no age/weight filter)";
}
}

// Step 2: For each recommended medicine, get its detailed configuration from FavouriteMedicine
if (diagnosisMedicineList != null && !diagnosisMedicineList.isEmpty()) {
System.out.println("DEBUG: Step 2 - Getting detailed configurations for " + diagnosisMedicineList.size() + " medicines");
Expand Down Expand Up @@ -1578,6 +1619,17 @@ public void addFavouriteDiagnosis() {
System.out.println("DEBUG: Age-based medicine config found " + (medicineConfigs != null ? medicineConfigs.size() : "null") + " results");
}

// Try no-filter if weight and age are both unavailable/zero
if (medicineConfigs == null || medicineConfigs.isEmpty()) {
medicineConfigs = favouriteController.listFavouriteItems(
diagnosisTemplate.getItem(),
PrescriptionTemplateType.FavouriteMedicine,
null,
null
);
System.out.println("DEBUG: No-filter medicine config found " + (medicineConfigs != null ? medicineConfigs.size() : "null") + " results");
}

// Use the first valid configuration found
if (medicineConfigs != null && !medicineConfigs.isEmpty()) {
PrescriptionTemplate medicineTemplate = medicineConfigs.get(0);
Expand All @@ -1586,7 +1638,11 @@ public void addFavouriteDiagnosis() {
" with dose=" + medicineTemplate.getDose() +
", frequency=" + (medicineTemplate.getFrequencyUnit() != null ? medicineTemplate.getFrequencyUnit().getName() : "null"));
} else {
System.out.println("DEBUG: No detailed configuration found for " + diagnosisTemplate.getItem().getName() + " - skipping");
// No separate FavouriteMedicine configuration exists for this medicine -
// fall back to the dose/frequency/duration already stored on the
// FavouriteDiagnosis template itself.
System.out.println("DEBUG: No separate FavouriteMedicine configuration found for " + diagnosisTemplate.getItem().getName() + " - using FavouriteDiagnosis template directly");
favouriteMedicines.add(diagnosisTemplate);
}
}
}
Expand Down Expand Up @@ -2165,6 +2221,7 @@ public void generateDocumentsFromDocumentTemplates(PatientEncounter encounter) {
for (DocumentTemplate t : dts) {
if (t.isDefaultTemplate()) {
ClinicalFindingValue cfv = new ClinicalFindingValue();
cfv.setClinicalFindingValueType(ClinicalFindingValueType.VisitPrescription);
cfv.setEncounter(encounter);
cfv.setDocumentTemplate(t);
cfv.setStringValue(t.getName());
Expand Down Expand Up @@ -2323,6 +2380,9 @@ private void updateOrGeneratePrescription() {
}
if (encounterPrescreption != null) {
encounterPrescreption.setLobValue(generateDocumentFromTemplate(encounterPrescreption.getDocumentTemplate(), current));
if (encounterPrescreption.getClinicalFindingValueType() == null) {
encounterPrescreption.setClinicalFindingValueType(ClinicalFindingValueType.VisitPrescription);
}
if (encounterPrescreption.getId() == null) {
clinicalFindingValueFacade.create(encounterPrescreption);
} else {
Expand All @@ -2339,7 +2399,7 @@ private void updateOrGeneratePrescription() {
}
if (prescTemplate != null) {
encounterPrescreption = new ClinicalFindingValue();
encounterPrescreption.setClinicalFindingValueType(ClinicalFindingValueType.VisitDocument);
encounterPrescreption.setClinicalFindingValueType(ClinicalFindingValueType.VisitPrescription);
encounterPrescreption.setDocumentTemplate(prescTemplate);
encounterPrescreption.setEncounter(current);
encounterPrescreption.setLobValue(generateDocumentFromTemplate(prescTemplate, current));
Expand Down Expand Up @@ -3842,9 +3902,31 @@ private List<ClinicalFindingValue> fillEncounterDocuments(PatientEncounter encou
}

private List<ClinicalFindingValue> fillEncounterPrescreptions(PatientEncounter encounter) {
List<ClinicalFindingValueType> clinicalFindingValueTypes = new ArrayList<>();
clinicalFindingValueTypes.add(ClinicalFindingValueType.VisitPrescription);
return loadCurrentEncounterFindingValues(encounter, clinicalFindingValueTypes);
List<ClinicalFindingValue> vs = new ArrayList<>();
if (encounterFindingValues == null) {
encounterFindingValues = fillEncounterFindingValues(encounter);
}
if (encounterFindingValues == null) {
encounterFindingValues = new ArrayList<>();
}
for (ClinicalFindingValue v : encounterFindingValues) {
if (v == null) {
continue;
}
if (v.getClinicalFindingValueType() == ClinicalFindingValueType.VisitPrescription) {
vs.add(v);
continue;
}
// Legacy prescriptions were persisted with a null or VisitDocument type;
// recognise them through their document template type instead.
boolean legacyType = v.getClinicalFindingValueType() == null
|| v.getClinicalFindingValueType() == ClinicalFindingValueType.VisitDocument;
if (legacyType && v.getDocumentTemplate() != null
&& v.getDocumentTemplate().getType() == DocumentTemplateType.Prescription) {
vs.add(v);
}
}
return vs;
}

private List<ClinicalFindingValue> fillPlanOfAction(PatientEncounter encounter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ public String issuePharmacyBill() {
getPatientEncounterController().setEncounterPrescreption(firstPrescription);
logger.log(Level.FINE, "Set encounterPrescreption from list. Prescription ID: {0}", firstPrescription.getId());
} else {
// Clear any prescription left over from a previously processed encounter
getPatientEncounterController().setEncounterPrescreption(null);
logger.log(Level.FINE, "No prescriptions found in list");
}

Expand All @@ -374,15 +376,19 @@ public String issuePharmacyBill() {
logger.log(Level.FINE, "Prescription text status: {0}", hasPrescriptionText ? "found" : "not found");

if (hasPrescriptionText) {
getPharmacySaleController().setComment(prescriptionText);
getPharmacySaleController().setPrescriptionHtml(prescriptionText);
getPharmacySaleController().setComment(htmlToPlainText(prescriptionText));
logger.log(Level.FINE, "Set prescription text as comment (length: {0} characters)", prescriptionText.length());
} else {
getPharmacySaleController().setPrescriptionHtml(null);
logger.log(Level.FINE, "No prescription text to set");
}

getPatientEncounterController().fillEncounterMedicines(opdVisit);
for(ClinicalFindingValue cli :patientEncounterController.getEncounterMedicines()){
}
// Auto-load the prescribed medicines onto the retail sale bill, mirroring
// the inward prescription-to-dispensing conversion on the admission profile.
List<ClinicalFindingValue> encounterMedicines
= getPatientEncounterController().fillEncounterMedicines(opdVisit);
getPharmacySaleController().addBillItemsFromEncounterMedicines(encounterMedicines);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return "/pharmacy/pharmacy_bill_retail_sale?faces-redirect=true";
}

Expand Down Expand Up @@ -415,6 +421,26 @@ private String getPrescriptionText() {
}
}

/**
* Converts prescription HTML (Quill rich text) to readable plain text for
* the bill comment field, keeping line breaks for paragraphs and headings.
*/
private String htmlToPlainText(String html) {
if (html == null) {
return null;
}
return html
.replaceAll("(?i)<br\\s*/?>", "\n")
.replaceAll("(?i)</(p|h[1-6]|li|div|tr)>", "\n")
.replaceAll("<[^>]+>", "")
.replace("&nbsp;", " ")
.replace("&amp;", "&")
.replace("&lt;", "<")
.replace("&gt;", ">")
.replaceAll("\n{3,}", "\n\n")
.trim();
}

public void opdVisitFromServiceSession() {
// ////// // System.out.println("opd visit from service session ");
if (billSession == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ private TreeNode<PrivilegeHolder> createPrivilegeHolderTreeNodes() {
TreeNode pharmacyNode = new DefaultTreeNode(new PrivilegeHolder(null, "Pharmacy"), allNode);
new DefaultTreeNode(new PrivilegeHolder(Privileges.Pharmacy, "Pharmacy Menu"), pharmacyNode);
new DefaultTreeNode(new PrivilegeHolder(Privileges.PharmacyAdministration, "Pharmacy Administration"), pharmacyNode);
new DefaultTreeNode(new PrivilegeHolder(Privileges.PharmacyItemNameEdit, "Pharmacy Item Name Edit"), pharmacyNode);
new DefaultTreeNode(new PrivilegeHolder(Privileges.PharmacyDonation, "Pharmacy Donation"), pharmacyNode);

// Channelling Privileges
Expand Down
Loading
Loading