Skip to content

Commit

Permalink
24.3 fb notification revamps (#720)
Browse files Browse the repository at this point in the history
* - In Blood Draws Today (All, Animal Care, and Vet Staff), I changed 'Assignment Status' column header to 'Unassigned' and 'Completion Status' to 'Incomplete'.  I also sorted all results so Incomplete draws show up first.
- In BloodDrawReviewTriggerNotification, I made it so warnings only send when the draw has a date of today.
- In BloodDrawReviewDailyNotification, I added a check to verify that there are no upcoming blood draws that will overdraw.

- TODO: After testing this on test servers, make sure to remove test dates in BloodDrawsTodayAll and BloodDrawReviewDailyNotification.

* Migrated automated test changes from 23.11 to 24.3.  23.11_notificationRevamps is now ready to be deleted.

* Added blood overdraw trigger notification.

* Registered new notification.

* Updated code so message sends when testing/running in browser.  Updated log for wnprc_triggers.js for when function is run to help debug until issue with webpack generation is fixed.

* Updated overdraw notification.  Notification is now created everytime blood is updated.  Logic is run inside notification to determine if current draw is an overdraw.  If it is an overdraw, the message is sent.

* Fixed issue where 'Animal Replacement Fee' showed incorrectly in the revamped Death Notification.  This occurred when the Type of Death resulted in a fee in the table 'ehr_lookups' > 'death_cause', but the 'prepaid' field was empty in the table 'study' > 'demographics'.  This was due to labkeys table lookup resulting in a string 'null' instead of a real null when using the TableSelector.  My new notifications use a new query function i wrote, but this Death Notification used the old TableSelector method.

* Reordered messages in BloodDrawReviewDailyNotification.java so overdraws are listed first.

* -NotificationToolkit.java: Updated getWeightFromAnimalID() and getSexFromAnimalID() so they use new query function getTableMultiRowMultiColumnWithFieldKeys() instead of old function getTableRowAsList().  Also moved DeathNecropsyObject and DeathDemographicObject to DeathNotificationRevamp.java.
- DeathNotificationRevamp.java: Moved DeathNecropsyObject and DeathDemographicObject here from NotificationToolkit.java.  Also cleaned up these objects and updated these them to use the new query getTableMultiRowMultiColumnWithFieldKeys.

* Removed automated tests that don't aren't finished.

* Added 2 new functions to NotificationToolkit for creating URL's.  This is to avoid hardcoding URL's per new LabKey policy.  Implimented these 2 new functions in DeathNotificationRevamp.java for getting the necropsy and animal abstract URL's.

* Adding automated tests for notifications.

* - WNPRC_EHRTest.java: Added notification setup function, multiple notification check functions, and a toolkit object containing reusable test functions that are commonly used when writing different tests.
- BloodOverdrawTriggerNotification.java & BloodDrawReviewTriggerNotification.java: Added a reset function to clear the data after notification is triggered.  This is because there are null checks that don't work when artifacts are left over from previous instances.
- NotificationToolkit.java: Added null check to checkIfBloodDrawIsOverdraw() because empty data was crashing the function.

* - DeathNotificationRevamp.java: Added a null check to make sure class doesn't cause a failure if there's no taskID in the row returned from the query.
- WNPRC_EHRTest.java: Added a check for death notification and prenatal death notification.

* Added null check before sending blood overdraw trigger manually.  The built in labkey notification setup just doesn't send a notification if there's a null body, but for my trigger notifications where I send it manually, I should check for null.

* Moved the automated tests to the end of the list and removed the @test flag.

* Disabled site-wide notifications.  Also disable individual notifications.

* Re-added 'test' tag before function.  Originally removed this because Marty said it was not necessary if I called the function in doSetup(), but it's not showing up in the console log anymore.  Trying to re-add this.

* Added try/catch for insertValueIntoBloodBilledByDataset due to duplicate data being uploaded.  Looks like labkey's loadBloodBilledByLookup() already uploads the same values.

* Added try/catch for remaining functions that insert into datasets.

* Changed a query function in checkIfAnimalIsAlive() so it no longer references my functions that use QviewObject.  Need to evenutally phase out all these functions as my new query functions work much better.

* Removing migrated alerts from ehrcron to Java based notifications

* Added comment to leave commented-out code block alone.  This will be used for future notifications, and it's very tough coding this correctly in the right order.  Please do not delete.

* Removed function call for notification tests in doSetup().  This was recommended by Binal via a LabKey ticket; it caused my test to run twice since the @test annotation already exists.

* - TriggerScriptHelper.java: Added trigger call for new AnimalRequestUpdateNotificationRevamp notification.  Also moved call for old notification inside if/else statement so 'on/off' status is checked before sending.  Will delete the old call after vefifying new version works well.

- WNPRC_EHRModule.java: Registered new EmptyNotificationRevamp and AnimalRequestUpdateNotificationRevamp notifications.

- AdminAlertsNotificationRevamp.java: Updated this notification so the days of the week are displayed in the correct order.  Also fixed an error with the wrong results being queried (needed to update the filter).

- AnimalRequestNotificationRevamp.java: Added test data to be set when notification is triggered from 'Run Report in Browser'.  Also added a resetClass function.

- AnimalRequestUpdateNotificationRevamp.java:  Created this new revamped notification.

- ColonyAlertsLiteNotificationRevamp.java: Updated this notification to use the new EmptyNotificationRevamp notification.  This is sent instead of the original notification if there is no data to be sent.

- EmptyNotificationRevamp.java: Created this new revamped notification.  This is sent when certain notifications have no data to send.  This is to prevent users from receiving empty emails, but allows Daniel and I to see that the notifications are still being sent.

- NotificationToolkit.java: Added function to send the new EmptyNotificationRevamp.java notification.

* - TriggerScriptHelper.java: Added 'sendManually' function call that I had forgotten.
- BloodDrawReviewDailyNotification.java: Added 2 extra checks requested by blood draw team.
- BloodDrawsTodayAnimalCare.java: Updated this to use the new dummy notification when there is no data to be sent.

* - animal_requests.js: Added fix for fatal issue with qcstatus being different in dataset and form.
- ColonyAlertsNotificationRevamp.java: Added extra query requested by Kim.  This query checks all animals in the 'Assignments' dataset and returns any where the project has expired or the protocol has deactivated.

* - WNPRC_EHRModule.java: Registered new notification.
- TreatmentAlertsNotificationRevamp.java: Created new notification.
- BloodDrawsTodayAll.java: Added 'incomplete count' to the notification (as requested by blood draw team).
- BloodDrawsTodayVetStaff.java: Added functionality so message does not send when there is no data (as requested by blood draw team).

* Removed joda time import statement because it was unused.

* ClinpathRefRange.sql - Added units column to table for data retrieval in ClinpathAbnormalResultsAlertsRevamp.java.
WNPRC_EHRModule.java - Registered the 2 new notifications.
ClinpathAbnormalResultsAlertsRevamp.java - Created new alert.
ClinpathAlertsRevamp.java - Created new alert.

* ClinpathResultAlertsRevamp.java: Created new revamp notification.
WNPRC_EHRModule.java: Registered new notification.

* LargeInfantAlertsRevamp.java: Created new revamped notification.
WNPRC_EHRModule.java: Registered new LargeInfantAlertwsRevamp notification.

* ClinpathAbnormalResultsAlertsRevamp.java: Fixed text display, typos, and filter.
ClinpathAlertsRevamp.java: Fixed text display.
ClinpathResultAlertsRevamp.java: Fixed filter.
ColonyAlertsNotificationRevamp.java: Added Kim's fix (there was an issue where the query retrieved inactive projects.
LargeInfantAlertsRevamp.java: Fixed text display.

* TreatmentAlertsNotificationRevamp.java: Fixed line spacing before & after areas & rooms.  Also removed unnecessary hyperlink tags.
ClinpathAbnormalResultsAlertsRevamp.java: Fixed table result to only show results with an alert status set to true (i.e. high, low, or blank status in the table).  Fixed line spacing before & after areas & rooms.  Also removed unnecessary hyperlink tags.  Fixed issue with DATE_GTE stripping time from query parameter.
ClinpathResultsAlertsRevamp.java: Fixed line spacing before & after areas & rooms.
ClinpathAlertsRevamp.java: Fixed issue with DATE_GTE stripping time from query parameter.

---------

Co-authored-by: F. Daniel Nicolalde <[email protected]>
  • Loading branch information
aschmidt34 and dnicolalde authored Jan 7, 2025
1 parent 3f8eb87 commit c7188f8
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ public String getMessageBodyHTML(Container c, User u) {

// Creates filter.
SimpleFilter myFilter = new SimpleFilter("qcstate/PublicData", true, CompareType.EQUAL);
myFilter.addCondition("taskid/datecompleted", lastRunDate, CompareType.DATE_GTE);
myFilter.addCondition("taskid/datecompleted", lastRunDate, CompareType.GTE);
myFilter.addCondition("taskid/datecompleted", "", CompareType.NONBLANK);
myFilter.addCondition("date", lastRunMinusWeek, CompareType.DATE_GTE);
myFilter.addCondition("date", lastRunMinusWeek, CompareType.GTE);
// Creates columns to retrieve.
String[] targetColumns = new String[]{"Id", "date", "Id/curLocation/area", "Id/curLocation/room", "Id/curLocation/cage", "alertStatus", "taskid/datecompleted", "testid", "result", "units", "status", "ref_range_min", "ref_range_max", "ageAtTime"};
// Runs query.
Expand All @@ -102,52 +102,54 @@ public String getMessageBodyHTML(Container c, User u) {
for (HashMap<String, String> result : returnArray) {
// Verifies 'alert status' exists before adding results.
if (!result.get("alertStatus").isEmpty()) {
// Updates current location.
if (result.get("Id/curLocation/area").isEmpty()) {
result.put("Id/curLocation/area", "No Active Housing");
}
// Updates current room.
if (result.get("Id/curLocation/room").isEmpty()) {
result.put("Id/curLocation/room", "No Room");
}
if (result.get("alertStatus").equals("t")) {
// Updates current location.
if (result.get("Id/curLocation/area").isEmpty()) {
result.put("Id/curLocation/area", "No Active Housing");
}
// Updates current room.
if (result.get("Id/curLocation/room").isEmpty()) {
result.put("Id/curLocation/room", "No Room");
}

// Adds to list if area does not exist yet.
if (!filteredResults.containsKey(result.get("Id/curLocation/area"))) {
// Creates new room results list.
ArrayList<HashMap<String, String>> newRoomList = new ArrayList<>();
newRoomList.add(result);
// Creates new room map.
HashMap<String, ArrayList<HashMap<String, String>>> newRoom = new HashMap<>();
newRoom.put(result.get("Id/curLocation/room"), newRoomList);
// Creates new area map and adds to the filtered results.
filteredResults.put(result.get("Id/curLocation/area"), newRoom);
}
// Adds to list if room does not exist yet.
else if (!filteredResults.get(result.get("Id/curLocation/area")).containsKey(result.get("Id/curLocation/room"))) {
// Creates new room results list.
ArrayList<HashMap<String, String>> newRoomList = new ArrayList<>();
newRoomList.add(result);
// Creates new room map and adds to the areas list.
filteredResults.get(result.get("Id/curLocation/area")).put(result.get("Id/curLocation/room"), newRoomList);
}
// Adds to list if area and room exist already.
else {
filteredResults.get(result.get("Id/curLocation/area")).get(result.get("Id/curLocation/room")).add(result);
// Adds to list if area does not exist yet.
if (!filteredResults.containsKey(result.get("Id/curLocation/area"))) {
// Creates new room results list.
ArrayList<HashMap<String, String>> newRoomList = new ArrayList<>();
newRoomList.add(result);
// Creates new room map.
HashMap<String, ArrayList<HashMap<String, String>>> newRoom = new HashMap<>();
newRoom.put(result.get("Id/curLocation/room"), newRoomList);
// Creates new area map and adds to the filtered results.
filteredResults.put(result.get("Id/curLocation/area"), newRoom);
}
// Adds to list if room does not exist yet.
else if (!filteredResults.get(result.get("Id/curLocation/area")).containsKey(result.get("Id/curLocation/room"))) {
// Creates new room results list.
ArrayList<HashMap<String, String>> newRoomList = new ArrayList<>();
newRoomList.add(result);
// Creates new room map and adds to the areas list.
filteredResults.get(result.get("Id/curLocation/area")).put(result.get("Id/curLocation/room"), newRoomList);
}
// Adds to list if area and room exist already.
else {
filteredResults.get(result.get("Id/curLocation/area")).get(result.get("Id/curLocation/room")).add(result);
}
}
}
}

// Prints text.
messageBody.append("There have been " + returnArray.size() + " clinpath tasks completed since " + lastRunDate + "<br>");
messageBody.append(notificationToolkit.createHyperlink("Click here to view them", clinpathTasksUrlView) + "</a><p>\n");
messageBody.append("<p>Listed below are the abnormal records.</p>\n");
messageBody.append(notificationToolkit.createHyperlink("Click here to view them", clinpathTasksUrlView) + "<p>\n");
messageBody.append("<p>Listed below are the abnormal records.<br>\n");

// Prints table with all records.
String[] tableColumns = new String[]{"Id", "Collect Date", "Date Completed", "Test ID", "Result", "Units", "Status", "Ref Range Min", "Ref Range Max", "Age At Time"};
for (String currentArea : notificationToolkit.sortSetWithNulls(filteredResults.keySet())) {
messageBody.append("<b>" + currentArea + ":</b><br>\n");
messageBody.append("<br>\n<b>" + currentArea + ":</b><br>\n");
for (String currentRoom : notificationToolkit.sortSetWithNulls(filteredResults.get(currentArea).keySet())) {
messageBody.append(currentRoom + ":<br>\n");
messageBody.append("<br>\n" + currentRoom + ":\n");
// Reformats the hashmap into a String[] List (to be compatible with the table creation function).
ArrayList<String []> currentTableData = new ArrayList<>();
ArrayList<String> rowColorsList = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public ClinpathAlertsObject(Container currentContainer, User currentUser, Date l
private void getRecordsRequestedSinceLastEmail() {
// Creates filter.
SimpleFilter myFilter = new SimpleFilter("qcstate/label", "Request: Pending", CompareType.EQUAL);
myFilter.addCondition("created", dateLastRun, CompareType.DATE_GTE);
myFilter.addCondition("created", dateLastRun, CompareType.GTE);
// Creates columns to retrieve.
String[] targetColumns = new String[]{"created"};
// Runs query.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ else if (!filteredResults.get(result.get("Id/curLocation/area")).containsKey(res
// Creates a table from the data.
String[] tableColumns = new String[]{"Id", "Collect Date", "Service Requested", "Requestor", "Date Reviewed", "Reviewed By"};
for (String currentArea : notificationToolkit.sortSetWithNulls(filteredResults.keySet())) {
messageBody.append("<b>" + currentArea + ":</b><br>\n");
messageBody.append("<br>\n<b>" + currentArea + ":</b><br>\n");
for (String currentRoom : notificationToolkit.sortSetWithNulls(filteredResults.get(currentArea).keySet())) {
messageBody.append(currentRoom + ":<br>\n");
messageBody.append("<br>\n" + currentRoom + ":\n");
// Reformats the hashmap into a String[] List (to be compatible with the table creation function).
ArrayList<String []> currentTableData = new ArrayList<>();
ArrayList<String> rowColorsList = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public String getMessageBodyHTML(Container c, User u) {
// 1. Shows all rooms lacking observations today.
if (!myTreatmentAlertsObject.roomsLackingObservationsToday.isEmpty()) {
messageBody.append("<b>WARNING: The following rooms do not have any obs for today as of: " + dateToolkit.getCurrentTime() + ".</b>");
messageBody.append("" + notificationToolkit.createHyperlink("Click here to view them.</a><p>\n", myTreatmentAlertsObject.roomsLackingObservationsTodayUrlView));
messageBody.append("" + notificationToolkit.createHyperlink(" Click here to view them.<p>\n", myTreatmentAlertsObject.roomsLackingObservationsTodayUrlView));
for (HashMap<String, String> result : myTreatmentAlertsObject.roomsLackingObservationsToday) {
messageBody.append(result.get("room") + "<br>");
}
Expand All @@ -94,7 +94,7 @@ public String getMessageBodyHTML(Container c, User u) {
// 2. Shows all treatments where the animal is not assigned to that project.
if (!myTreatmentAlertsObject.treatmentsWithAnimalNotAssignedToProject.isEmpty()) {
messageBody.append("<b>WARNING: There are " + myTreatmentAlertsObject.treatmentsWithAnimalNotAssignedToProject.size() + " scheduled treatments where the animal is not assigned to the project.</br><br>");
messageBody.append("" + notificationToolkit.createHyperlink("Click here to view them.</a><br>\n", myTreatmentAlertsObject.treatmentsWithAnimalNotAssignedToProjectUrlView));
messageBody.append("" + notificationToolkit.createHyperlink(" Click here to view them.<br>\n", myTreatmentAlertsObject.treatmentsWithAnimalNotAssignedToProjectUrlView));
messageBody.append("<hr>\n");
}
// 3. Shows treatments for each time of day.
Expand All @@ -106,7 +106,7 @@ public String getMessageBodyHTML(Container c, User u) {
Integer totalTreatments = myTreatmentAlertsObject.incompleteTreatmentsForEachTimeOfDay.get(timeOfDay).size() + myTreatmentAlertsObject.completedTreatmentCountsForEachTimeOfDay.get(timeOfDay);
if (totalTreatments > 0) {
messageBody.append("There are " + totalTreatments + " scheduled " + timeOfDay + " treatments. " + myTreatmentAlertsObject.completedTreatmentCountsForEachTimeOfDay.get(timeOfDay) + " have been completed. ");
messageBody.append("" + notificationToolkit.createHyperlink("Click here to view them.</a></p>\n", myTreatmentAlertsObject.treatmentsForEachTimeOfDayUrlView.get(timeOfDay)));
messageBody.append("" + notificationToolkit.createHyperlink("Click here to view them.<br>\n", myTreatmentAlertsObject.treatmentsForEachTimeOfDayUrlView.get(timeOfDay)));

// Creates the current timeOfDay results sorted by (area --> room --> result).
HashMap<String, HashMap<String, ArrayList<HashMap<String, String>>>> resultsByArea = new HashMap<>();
Expand Down Expand Up @@ -141,10 +141,10 @@ else if (!resultsByArea.get(currentArea).containsKey(currentRoom)) {

// Iterates through each area (sorted alphabetically).
for (String currentArea : notificationToolkit.sortSetWithNulls(resultsByArea.keySet())) {
messageBody.append("<b>" + currentArea + ":</b><br>\n");
messageBody.append("<br>\n<b>" + currentArea + ":</b><br>\n");
// Iterates through each room (sorted alphabetically)
for (String currentRoom : notificationToolkit.sortSetWithNulls(resultsByArea.get(currentArea).keySet())) {
messageBody.append(currentRoom + ": " + resultsByArea.get(currentArea).get(currentRoom).size() + "<br>\n");
messageBody.append("<br>\n" + currentRoom + ": " + resultsByArea.get(currentArea).get(currentRoom).size() + "\n");
// Reformats the treatment hashmap into a String[] List (to be compatible with the table creation function).
ArrayList<String []> formattedResults = new ArrayList<>();
for (HashMap<String, String> currentTreatment : resultsByArea.get(currentArea).get(currentRoom)) {
Expand Down Expand Up @@ -188,13 +188,13 @@ else if (!resultsByArea.get(currentArea).containsKey(currentRoom)) {
// 5. Shows any treatments where the animal is not alive.
if (!myTreatmentAlertsObject.treatmentsWhereAnimalIsNotAlive.isEmpty()) {
messageBody.append("<b>WARNING: There are " + myTreatmentAlertsObject.treatmentsWhereAnimalIsNotAlive.size() + " active treatments for animals not currently at WNPRC.</b>");
messageBody.append("" + notificationToolkit.createHyperlink("Click here to view and update them.</a><br>\n", myTreatmentAlertsObject.treatmentsWhereAnimalIsNotAliveURLView));
messageBody.append("" + notificationToolkit.createHyperlink(" Click here to view and update them.<br>\n", myTreatmentAlertsObject.treatmentsWhereAnimalIsNotAliveURLView));
messageBody.append("<hr>\n");
}
// 6. Find any problems where the animal is not alive.
if (!myTreatmentAlertsObject.problemsWhereAnimalIsNotAlive.isEmpty()) {
messageBody.append("<b>WARNING: There are " + myTreatmentAlertsObject.problemsWhereAnimalIsNotAlive.size() + " unresolved problems for animals not currently at WNPRC.</b>");
messageBody.append("" + notificationToolkit.createHyperlink("Click here to view and update them.</a><br>\n", myTreatmentAlertsObject.problemsWhereAnimalIsNotAliveUrlView));
messageBody.append("" + notificationToolkit.createHyperlink(" Click here to view and update them.<br>\n", myTreatmentAlertsObject.problemsWhereAnimalIsNotAliveUrlView));
messageBody.append("<hr>\n");
}
// 7. Checks for missing In Rooms after 2:30pm, as specified in the SOP.
Expand Down

0 comments on commit c7188f8

Please sign in to comment.