Skip to content
65 changes: 65 additions & 0 deletions src/main/java/com/divudi/bean/common/NotificationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ public void createNotification(PatientRoom pr, String action) {
case "Discharge":
createInwardRoomDischargeNotifications(pr);
break;
case "Admit":
createInwardRoomAdmitNotifications(pr);
break;
case "Change":
createInwardRoomChangeNotifications(pr);
break;
case "CancelDischarge":
createInwardRoomDischargeCancelNotifications(pr);
break;

default:
throw new AssertionError();
Expand Down Expand Up @@ -165,6 +174,62 @@ private void createInwardRoomDischargeNotifications(PatientRoom pr) {
}
}

private void createInwardRoomAdmitNotifications(PatientRoom pr) {
Date date = new Date();
for (TriggerType tt : TriggerType.getTriggersByParent(TriggerTypeParent.INWARD_PATIENT_ROOM_ADDED)) {
Notification nn = new Notification();
nn.setCreatedAt(date);
nn.setPatientRoom(pr);
nn.setTriggerType(tt);
nn.setCreater(sessionController.getLoggedUser());
String roomName = pr.getRoomFacilityCharge() != null ? pr.getRoomFacilityCharge().getName() : "Unknown Room";
String patientName = "";
if (pr.getPatientEncounter() != null && pr.getPatientEncounter().getPatient() != null
&& pr.getPatientEncounter().getPatient().getPerson() != null) {
patientName = pr.getPatientEncounter().getPatient().getPerson().getNameWithTitle();
}
String msg = "Patient " + patientName + " admitted to " + roomName;
nn.setMessage(msg);
getFacade().create(nn);
userNotificationController.createUserNotifications(nn);
}
}

private void createInwardRoomChangeNotifications(PatientRoom pr) {
Date date = new Date();
for (TriggerType tt : TriggerType.getTriggersByParent(TriggerTypeParent.INWARD_PATIENT_ROOM_CHANGED)) {
Notification nn = new Notification();
nn.setCreatedAt(date);
nn.setPatientRoom(pr);
nn.setTriggerType(tt);
nn.setCreater(sessionController.getLoggedUser());
String roomName = pr.getRoomFacilityCharge() != null ? pr.getRoomFacilityCharge().getName() : "Unknown Room";
String msg = "Patient moved to " + roomName;
if (pr.getPatientEncounter() != null && pr.getPatientEncounter().getBhtNo() != null) {
msg = msg + " (BHT: " + pr.getPatientEncounter().getBhtNo() + ")";
}
nn.setMessage(msg);
getFacade().create(nn);
userNotificationController.createUserNotifications(nn);
}
}

private void createInwardRoomDischargeCancelNotifications(PatientRoom pr) {
Date date = new Date();
for (TriggerType tt : TriggerType.getTriggersByParent(TriggerTypeParent.INWARD_PATIENT_ROOM_DISCHARGED)) {
Notification nn = new Notification();
nn.setCreatedAt(date);
nn.setPatientRoom(pr);
nn.setTriggerType(tt);
nn.setCreater(sessionController.getLoggedUser());
String roomName = pr.getRoomFacilityCharge() != null ? pr.getRoomFacilityCharge().getName() : "Unknown Room";
String msg = "Room Discharge Cancelled for " + roomName;
nn.setMessage(msg);
getFacade().create(nn);
userNotificationController.createUserNotifications(nn);
}
}

private void createInwardClinicalDischargeNotifications(PatientEncounter pe) {
Date date = new Date();
for (TriggerType tt : TriggerType.getTriggersByParent(TriggerTypeParent.INWARD_PATIENT_CLINICAL_DISCHARGED)) {
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/divudi/bean/inward/AdmissionController.java
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,34 @@ public String navigateToPatientRoomDetails() {
return bhtSummeryController.navigateToPatientRoomDetails();
}

/**
* Returns the list of currently active (non-discharged, non-retired)
* PatientRoom and GuardianRoom records for the current admission.
* Used by the dashboard "Room Management" panel to display current room
* assignments.
*/
public List<com.divudi.core.entity.inward.PatientRoom> getActivePatientRooms() {
if (current == null) {
return java.util.Collections.emptyList();
}
List<com.divudi.core.entity.inward.PatientRoom> activeRooms = new java.util.ArrayList<>();
try {
String jpql = "SELECT pr FROM PatientRoom pr "
+ "WHERE pr.retired = false "
+ "AND pr.discharged = false "
+ "AND pr.patientEncounter = :enc "
+ "ORDER BY pr.createdAt";
java.util.HashMap<String, Object> params = new java.util.HashMap<>();
params.put("enc", current);
activeRooms = patientRoomFacade.findByJpql(jpql, params);
} catch (Exception e) {
logger.log(Level.SEVERE, "Failed to load active rooms for admission ID: "
+ (current != null ? current.getId() : null), e);
JsfUtil.addErrorMessage("Unable to load current room assignments.");
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return activeRooms;
}

public String navigateToAddBabyAdmission() {
parentAdmission = current;
Admission ad = new Admission();
Expand Down
104 changes: 101 additions & 3 deletions src/main/java/com/divudi/bean/inward/RoomChangeController.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public class RoomChangeController implements Serializable {
NotificationController notificationController;
@Inject
private InwardBeanController inwardBean;
@Inject
private com.divudi.bean.common.AuditEventApplicationController auditEventApplicationController;

@EJB
private AdmissionFacade ejbFacade;
Expand All @@ -84,6 +86,7 @@ public class RoomChangeController implements Serializable {

private List<PatientRoom> patientRoom;
private PatientRoom currentPatientRoom;
private PatientRoom roomForReceipt;
List<Admission> selectedItems;
private Admission current;
private List<Admission> items = null;
Expand Down Expand Up @@ -242,6 +245,9 @@ public void admitRoom() {
current.setRoomAdmitted(true);
ejbFacade.edit(current);

recordRoomAuditEvent(getCurrentPatientRoom(), "Room Admitted", null);
notificationController.createNotification(getCurrentPatientRoom(), "Admit");

JsfUtil.addSuccessMessage("Room admitted successfully");

}
Expand Down Expand Up @@ -281,6 +287,10 @@ public void remove(PatientRoom pR) {
return;
}

String beforeState = "roomFacilityCharge=" + (pR.getRoomFacilityCharge() != null ? pR.getRoomFacilityCharge().getName() : "null")
+ ", admittedAt=" + pR.getAdmittedAt()
+ ", discharged=" + pR.isDischarged();

pR.setRetirer(getSessionController().getLoggedUser());
pR.setRetired(true);
pR.setRetiredAt(new Date());
Expand All @@ -294,6 +304,8 @@ public void remove(PatientRoom pR) {
getCurrent().setCurrentPatientRoom(pR.getPreviousRoom());
getEjbFacade().edit(getCurrent());
}

recordRoomAuditEvent(pR, "Room Removed", beforeState);
}

public void discharge(PatientRoom pR) {
Expand All @@ -314,6 +326,8 @@ public void discharge(PatientRoom pR) {
encounter.setRoomDischargedBy(getSessionController().getLoggedUser());
patientEncounterFacade.edit(encounter);
}

recordRoomAuditEvent(pR, "Room Discharged", null);
}

public void dischargeWithCurrentTime(PatientRoom pR) {
Expand All @@ -323,7 +337,7 @@ public void dischargeWithCurrentTime(PatientRoom pR) {
List<PatientRoom> rooms = bhtSummeryController.getPatientRooms();
if (rooms != null) {
if (rooms.size() > 1) {
int currentRoomIndex = rooms.indexOf(patientRoom);
int currentRoomIndex = rooms.indexOf(pR);
if (currentRoomIndex > 0) {
PatientRoom previousRoom = rooms.get(currentRoomIndex - 1);

Expand All @@ -349,24 +363,97 @@ public void dischargeWithCurrentTime(PatientRoom pR) {
encounter.setRoomDischargedBy(getSessionController().getLoggedUser());
patientEncounterFacade.edit(encounter);
}

// Record audit event
recordRoomAuditEvent(pR, "Room Discharged", null);

JsfUtil.addSuccessMessage("Successfully Discharged from Room");
}

public void dischargeCancel(PatientRoom pR) {
if (pR == null) {
return;
}
// Capture state before cancel for audit
String beforeState = "discharged=true, dischargedAt=" + pR.getDischargedAt()
+ ", dischargedBy=" + (pR.getDischargedBy() != null ? pR.getDischargedBy().getName() : "null");

pR.setDischarged(false);
pR.setDischargedBy(null);
pR.setDischargedAt(null);
getPatientRoomFacade().edit(pR);

// Record audit event
recordRoomAuditEvent(pR, "Room Discharge Cancelled", beforeState);
notificationController.createNotification(pR, "CancelDischarge");

JsfUtil.addSuccessMessage("Room Discharge Cancelled");
}

private void recordRoomAuditEvent(PatientRoom pr, String trigger, String beforeState) {
try {
com.divudi.core.entity.AuditEvent auditEvent = new com.divudi.core.entity.AuditEvent();
auditEvent.setEventDataTime(new Date());
auditEvent.setEventTrigger(trigger);
auditEvent.setEntityType(pr.getClass().getSimpleName());
auditEvent.setObjectId(pr.getId());
if (pr.getPatientEncounter() != null) {
auditEvent.setUrl("BHT: " + pr.getPatientEncounter().getBhtNo()
+ " | Room: " + (pr.getRoomFacilityCharge() != null ? pr.getRoomFacilityCharge().getName() : "N/A"));
}
if (sessionController.getLoggedUser() != null) {
auditEvent.setWebUserId(sessionController.getLoggedUser().getId());
}
if (sessionController.getInstitution() != null) {
auditEvent.setInstitutionId(sessionController.getInstitution().getId());
}
if (sessionController.getDepartment() != null) {
auditEvent.setDepartmentId(sessionController.getDepartment().getId());
}
if (beforeState != null) {
auditEvent.setBeforeJson(beforeState);
}
String afterState = "discharged=" + pr.isDischarged()
+ ", dischargedAt=" + pr.getDischargedAt()
+ ", dischargedBy=" + (pr.getDischargedBy() != null ? pr.getDischargedBy().getName() : "null");
auditEvent.setAfterJson(afterState);
auditEvent.setEventStatus("Completed");
auditEvent.setEventDuration(new Date().getTime() - auditEvent.getEventDataTime().getTime());
auditEventApplicationController.logAuditEvent(auditEvent);
} catch (Exception e) {
// Silently fail â€" audit failure should not block the user action
}
}

public String navigateToRoomDischargeReceipt(PatientRoom pr) {
if (pr == null) {
JsfUtil.addErrorMessage("No room selected");
return "";
}
this.roomForReceipt = pr;
return "/inward/inward_room_discharge_receipt?faces-redirect=true";
}

public PatientRoom getRoomForReceipt() {
return roomForReceipt;
}

public void setRoomForReceipt(PatientRoom roomForReceipt) {
this.roomForReceipt = roomForReceipt;
}

public void removeRoom(PatientRoom pR) {
if (pR == null) {
JsfUtil.addErrorMessage("No Patient Room Detected");
return;
}
String beforeState = "room=" + (pR.getRoomFacilityCharge() != null ? pR.getRoomFacilityCharge().getName() : "null");
pR.setRetired(true);
pR.setRetiredAt(new Date());
pR.setRetirer(sessionController.getWebUser());
getPatientRoomFacade().edit(pR);
bhtSummeryController.setPatientRooms(null);
recordRoomAuditEvent(pR, "Room Removed", beforeState);
}

public void removeGuardianRoom(PatientRoom pR) {
Expand All @@ -376,6 +463,7 @@ public void removeGuardianRoom(PatientRoom pR) {
return;
}

String beforeState = "room=" + (pR.getRoomFacilityCharge() != null ? pR.getRoomFacilityCharge().getName() : "null");
pR.setRetirer(getSessionController().getLoggedUser());
pR.setRetired(true);
pR.setRetiredAt(new Date());
Expand All @@ -388,6 +476,7 @@ public void removeGuardianRoom(PatientRoom pR) {
getPatientRoomFacade().edit(pR.getPreviousRoom());
}

recordRoomAuditEvent(pR, "Guardian Room Removed", beforeState);
}

public void recreate() {
Expand Down Expand Up @@ -456,6 +545,9 @@ public void change() {
// Save consultant information
saveConsultantInfo(newPatientRoom);

recordRoomAuditEvent(newPatientRoom, "Room Changed", "previousRoom=" + (oldPatientRoom.getRoomFacilityCharge() != null ? oldPatientRoom.getRoomFacilityCharge().getName() : "null"));
notificationController.createNotification(newPatientRoom, "Change");

if (newConsultant != null || newPrimeConsultant != null) {
JsfUtil.addSuccessMessage("Room changed with consultant details");
} else {
Expand Down Expand Up @@ -489,7 +581,10 @@ public void addNewRoom() {
// Save consultant information
saveConsultantInfo(newPatientRoom);

JsfUtil.addSuccessMessage("Successfully Room Changed");
recordRoomAuditEvent(newPatientRoom, "Room Added", null);
notificationController.createNotification(newPatientRoom, "Admit");

JsfUtil.addSuccessMessage("Successfully Room Added");

newRoomFacilityCharge = null;
changeAt = null;
Expand Down Expand Up @@ -535,7 +630,10 @@ public void changeGurdianRoom() {
getPatientRoomFacade().edit(oldGaurdianRoom);
}

JsfUtil.addSuccessMessage("Successfully Room Changed");
recordRoomAuditEvent(newGuardianRoom, "Guardian Room Changed", oldGaurdianRoom != null ? "previousRoom=" + (oldGaurdianRoom.getRoomFacilityCharge() != null ? oldGaurdianRoom.getRoomFacilityCharge().getName() : "null") : "first guardian room");
notificationController.createNotification(newGuardianRoom, "Change");

JsfUtil.addSuccessMessage("Successfully Guardian Room Changed");
newRoomFacilityCharge = null;
changeAt = null;
createGuardianRoom();
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/divudi/core/data/TriggerType.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,15 @@ public enum TriggerType {
// Inward discharge — stage 2: room/bed discharge (bed released; typically notifies billing).
INWARD_PATIENT_ROOM_DISCHARGED("Inward Patient Room Discharge - System Notification", NotificationMedium.SYSTEM_NOTIFICATION, TriggerTypeParent.INWARD_PATIENT_ROOM_DISCHARGED),
INWARD_PATIENT_ROOM_DISCHARGED_SMS("Inward Patient Room Discharge - SMS", NotificationMedium.SMS, TriggerTypeParent.INWARD_PATIENT_ROOM_DISCHARGED),
INWARD_PATIENT_ROOM_DISCHARGED_EMAIL("Inward Patient Room Discharge - Email", NotificationMedium.EMAIL, TriggerTypeParent.INWARD_PATIENT_ROOM_DISCHARGED);
INWARD_PATIENT_ROOM_DISCHARGED_EMAIL("Inward Patient Room Discharge - Email", NotificationMedium.EMAIL, TriggerTypeParent.INWARD_PATIENT_ROOM_DISCHARGED),
// Inward room — patient admitted/added to a room
INWARD_PATIENT_ROOM_ADDED("Inward Patient Room Added - System Notification", NotificationMedium.SYSTEM_NOTIFICATION, TriggerTypeParent.INWARD_PATIENT_ROOM_ADDED),
INWARD_PATIENT_ROOM_ADDED_SMS("Inward Patient Room Added - SMS", NotificationMedium.SMS, TriggerTypeParent.INWARD_PATIENT_ROOM_ADDED),
INWARD_PATIENT_ROOM_ADDED_EMAIL("Inward Patient Room Added - Email", NotificationMedium.EMAIL, TriggerTypeParent.INWARD_PATIENT_ROOM_ADDED),
// Inward room — patient changed/moved to a different room
INWARD_PATIENT_ROOM_CHANGED("Inward Patient Room Changed - System Notification", NotificationMedium.SYSTEM_NOTIFICATION, TriggerTypeParent.INWARD_PATIENT_ROOM_CHANGED),
INWARD_PATIENT_ROOM_CHANGED_SMS("Inward Patient Room Changed - SMS", NotificationMedium.SMS, TriggerTypeParent.INWARD_PATIENT_ROOM_CHANGED),
INWARD_PATIENT_ROOM_CHANGED_EMAIL("Inward Patient Room Changed - Email", NotificationMedium.EMAIL, TriggerTypeParent.INWARD_PATIENT_ROOM_CHANGED);

private final String label;
private final NotificationMedium medium;
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/divudi/core/data/TriggerTypeParent.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public enum TriggerTypeParent {
OPD_BILL_CANCELLATION,
INWARD_PATIENT_CLINICAL_DISCHARGED,
INWARD_PATIENT_ROOM_DISCHARGED,
INWARD_PATIENT_ROOM_ADDED,
INWARD_PATIENT_ROOM_CHANGED,
INWARD_PATIENT_DISCHARGED,
FLOAT_TRANSFER_REQUEST
}
Loading
Loading