diff --git a/WNPRC_EHR/resources/queries/wnprc/animal_requests.js b/WNPRC_EHR/resources/queries/wnprc/animal_requests.js
index 2c9cfa381..81cac97da 100644
--- a/WNPRC_EHR/resources/queries/wnprc/animal_requests.js
+++ b/WNPRC_EHR/resources/queries/wnprc/animal_requests.js
@@ -90,6 +90,24 @@ function onAfterInsert(helper,errors,row){
function onAfterUpdate(helper,errors,row,oldRow){
var rowid = row.rowId;
var hostName = 'https://' + LABKEY.serverName;
- console.log ("animal_requests.js: New request updated, rowid: "+ rowid);
+ console.log("animal_requests.js: New request updated, rowid: "+ rowid);
+
+ if ("QCStateLabel" in row) {
+ delete row.QCState;
+ row["qcstate"] = row["QCStateLabel"];
+ delete row.QCStateLabel;
+ }
+ if ("QCStateLabel" in oldRow) {
+ oldRow["qcstate"] = oldRow["QCStateLabel"];
+ delete oldRow.QCStateLabel;
+ }
+
+ if ("_publicData" in row) {
+ delete row._publicData;
+ }
+ if ("_publicData" in oldRow) {
+ delete oldRow._publicData;
+ }
+
WNPRC.Utils.getJavaHelper().sendAnimalRequestNotificationUpdate(rowid, row, oldRow, hostName);
}
diff --git a/WNPRC_EHR/src/org/labkey/wnprc_ehr/WNPRC_EHRModule.java b/WNPRC_EHR/src/org/labkey/wnprc_ehr/WNPRC_EHRModule.java
index 7c9832694..abdebd68e 100644
--- a/WNPRC_EHR/src/org/labkey/wnprc_ehr/WNPRC_EHRModule.java
+++ b/WNPRC_EHR/src/org/labkey/wnprc_ehr/WNPRC_EHRModule.java
@@ -392,7 +392,8 @@ public void registerNotifications() {
new ColonyAlertsLiteNotificationRevamp(this),
new BloodOverdrawTriggerNotification(this),
new EmptyNotificationRevamp(this),
- new AnimalRequestUpdateNotificationRevamp(this)
+ new AnimalRequestUpdateNotificationRevamp(this),
+ new TreatmentAlertsNotificationRevamp(this)
);
for (Notification notification : notifications)
diff --git a/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/BloodDrawsTodayAll.java b/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/BloodDrawsTodayAll.java
index 8030b9204..e143099c2 100644
--- a/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/BloodDrawsTodayAll.java
+++ b/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/BloodDrawsTodayAll.java
@@ -81,18 +81,17 @@ public String getMessageBodyHTML(Container c, User u) {
// Prints all tables.
if (myBloodDrawNotificationObject.resultsByArea.isEmpty()) {
- messageBody.append("There are no scheduled blood draws for this group today.");
+ messageBody.append("There are no scheduled blood draws today.");
}
else {
+ messageBody.append("
REMAINING INCOMPLETE TOTALS:
\n");
+ messageBody.append("Animal Care: " + myBloodDrawNotificationObject.numIncompleteAnimalCare + "\n");
+ messageBody.append("Research Staff: " + myBloodDrawNotificationObject.numIncompleteResearchStaff + "\n");
+ messageBody.append("SPI: " + myBloodDrawNotificationObject.numIncompleteSPI + "\n");
+ messageBody.append("Vet Staff: " + myBloodDrawNotificationObject.numIncompleteVetStaff + "
");
messageBody.append(myBloodDrawNotificationObject.printTablesAsHTML());
}
-// // Creates table.
-// String[] myTableColumns = new String[]{"Id", "Blood Remaining", "Project Assignment", "Completion Status", "Group", "Other Groups Drawing Blood Today"};
-// NotificationToolkit.NotificationRevampTable myTable = new NotificationToolkit.NotificationRevampTable(myTableColumns, myBloodDrawNotificationObject.myTableData);
-// myTable.rowColors = myBloodDrawNotificationObject.myTableRowColors;
-// messageBody.append(myTable.createBasicHTMLTable());
-
return messageBody.toString();
}
@@ -105,8 +104,11 @@ public static class BloodDrawsTodayObject {
NotificationToolkit.DateToolkit dateToolkit = new NotificationToolkit.DateToolkit();
ArrayList myTableData = new ArrayList<>(); // List of all blood draws as [[id, blood remaining, project assignment, completion status, assigned to]]
- // ArrayList myTableRowColors = new ArrayList<>(); // List of all row colors (same length as myTableData).
HashMap>> resultsByArea = new HashMap<>(); // Area(Room(List of draws))
+ Integer numIncompleteSPI = 0;
+ Integer numIncompleteAnimalCare = 0;
+ Integer numIncompleteVetStaff = 0;
+ Integer numIncompleteResearchStaff = 0;
//Gets all info for the BloodDrawNotificationObject.
@@ -145,8 +147,10 @@ public static class BloodDrawsTodayObject {
// Updates id.
myCurrentRow[0] = result.get("id");
+
// Updates blood remaining.
myCurrentRow[1] = result.get("BloodRemaining/AvailBlood");
+
// Updates project status (this checks if animal is assigned to a project).
if (!result.get("qcstate/label").equals("Request: Denied") && !result.get("projectStatus").isEmpty()) {
myCurrentRow[2] = "UNASSIGNED";
@@ -154,6 +158,7 @@ public static class BloodDrawsTodayObject {
else {
myCurrentRow[2] = "";
}
+
// Updates completion status (this checks if blood draw has been completed).
if (!result.get("qcstate/label").equals("Completed")) {
myCurrentRow[3] = "INCOMPLETE";
@@ -161,8 +166,10 @@ public static class BloodDrawsTodayObject {
else {
myCurrentRow[3] = "";
}
+
// Updates the current group assigned to this animal.
myCurrentRow[4] = result.get("billedby/title");
+
// Updates the current area.
if (!result.get("Id/curLocation/area").isEmpty()) {
myCurrentRow[6] = result.get("Id/curLocation/area");
@@ -170,6 +177,7 @@ public static class BloodDrawsTodayObject {
else {
myCurrentRow[6] = "Unknown Area";
}
+
// Updates the current room.
if (!result.get("Id/curLocation/room").isEmpty()) {
myCurrentRow[7] = result.get("Id/curLocation/room");
@@ -191,18 +199,6 @@ else if (availBlood <= bloodThreshold) {
myCurrentRow[8] = "orange";
}
}
-// String currentRowColor = "white";
-// if (!result.get("BloodRemaining/AvailBlood").isEmpty()) {
-// Float availBlood = Float.parseFloat(result.get("BloodRemaining/AvailBlood"));
-// if (availBlood <= 0) {
-// // If blood draw is over limit, color it red.
-// currentRowColor = "red";
-// }
-// else if (availBlood <= bloodThreshold) {
-// // If blood draw is over threshold limit, color it orange.
-// currentRowColor = "orange";
-// }
-// }
// Adds the current row to myTableData (based on group being queried).
if (assignmentGroup.equals("animalCare")) {
@@ -234,6 +230,24 @@ else if (assignmentGroup.equals("vetStaff")) {
myTableData.add(myCurrentRow);
}
}
+
+ // Updates number of incomplete draws.
+ if (assignmentGroup.equals("all")) {
+ if (myCurrentRow[3].equals("INCOMPLETE")) {
+ if (result.get("billedby/title").equals("SPI")) {
+ numIncompleteSPI++;
+ }
+ else if (result.get("billedby/title").equals("Animal Care")) {
+ numIncompleteAnimalCare++;
+ }
+ else if (result.get("billedby/title").equals("Research Staff")) {
+ numIncompleteResearchStaff++;
+ }
+ else if (result.get("billedby/title").equals("Vet Staff")) {
+ numIncompleteVetStaff++;
+ }
+ }
+ }
}
//Goes through each draw to find draws scheduled for more than one group, then updates myTableData with information.
diff --git a/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/BloodDrawsTodayVetStaff.java b/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/BloodDrawsTodayVetStaff.java
index 35de535fd..a4ebcd972 100644
--- a/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/BloodDrawsTodayVetStaff.java
+++ b/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/BloodDrawsTodayVetStaff.java
@@ -69,17 +69,13 @@ public String getMessageBodyHTML(Container c, User u) {
// Creates table.
if (myBloodDrawNotificationObject.resultsByArea.isEmpty()) {
- messageBody.append("There are no scheduled blood draws for this group today.");
+ notificationToolkit.sendEmptyNotificationRevamp(c, u, "Blood Draws Today (Vet Staff)");
+ return null;
}
else {
messageBody.append(myBloodDrawNotificationObject.printTablesAsHTML());
+ return messageBody.toString();
}
-// String[] myTableColumns = new String[]{"Id", "Blood Remaining", "Project Assignment", "Completion Status", "Group", "Other Groups Drawing Blood Today"};
-// NotificationToolkit.NotificationRevampTable myTable = new NotificationToolkit.NotificationRevampTable(myTableColumns, myBloodDrawNotificationObject.myTableData);
-// myTable.rowColors = myBloodDrawNotificationObject.myTableRowColors;
-// messageBody.append(myTable.createBasicHTMLTable());
-
- return messageBody.toString();
}
}
diff --git a/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/ColonyAlertsNotificationRevamp.java b/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/ColonyAlertsNotificationRevamp.java
index bda4861a3..872a428e8 100644
--- a/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/ColonyAlertsNotificationRevamp.java
+++ b/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/ColonyAlertsNotificationRevamp.java
@@ -27,6 +27,8 @@
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
@@ -41,6 +43,8 @@
import javax.script.ScriptEngine;
+import static org.labkey.api.search.SearchService._log;
+
/**
* Created by Alex Schmidt on 12/27/23.
@@ -97,6 +101,12 @@ public String getMessageBodyHTML(Container c, User u) {
final StringBuilder messageBody = new StringBuilder();
ColonyInformationObject myColonyAlertObject = new ColonyInformationObject(c, u, "colonyAlert");
+ // Creates CSS.
+ messageBody.append(styleToolkit.beginStyle());
+ messageBody.append(styleToolkit.setBasicTableStyle());
+ messageBody.append(styleToolkit.setHeaderRowBackgroundColor("#d9d9d9"));
+ messageBody.append(styleToolkit.endStyle());
+
//Begins message info.
messageBody.append(" This email contains a series of automatic alerts about the colony. It was run on: " + dateToolkit.getCurrentTime() + ".
");
@@ -373,6 +383,19 @@ public String getMessageBodyHTML(Container c, User u) {
messageBody.append(notificationToolkit.createHyperlink("Click here to view them
\n", myColonyAlertObject.totalFinalizedRecordsWithFutureDatesURLView));
messageBody.append("
\n");
}
+ //38. Find any animals assigned to an inactivated project or deactivated protocol.
+ if (!myColonyAlertObject.animalsWithInvalidProjectOrProtocol.isEmpty()) {
+ // Creates HTML table to return.
+ String[] myTableColumns = new String[]{"Id", "Project", "Project End Date", "Protocol", "Protocol End Date"};
+ NotificationToolkit.NotificationRevampTable myTable = new NotificationToolkit.NotificationRevampTable(myTableColumns, myColonyAlertObject.animalsWithInvalidProjectOrProtocol);
+
+ // Displays message.
+ messageBody.append("WARNING: There are " + myColonyAlertObject.animalsWithInvalidProjectOrProtocol.size() + " living animals with inactivated projects or deactivated protocols.
");
+ messageBody.append(myTable.createBasicHTMLTable());
+ messageBody.append(notificationToolkit.createHyperlink("Click here to view all Assignments.
\n", myColonyAlertObject.animalsWithInvalidProjectOrProtocolURLView));
+ messageBody.append("
\n");
+
+ }
//Returns string.
return messageBody.toString();
@@ -469,6 +492,8 @@ public ColonyInformationObject(Container currentContainer, User currentUser, Str
getPrenatalDeathsInLastFiveDays();
//37. Find the total finalized records with future dates.
getTotalFinalizedRecordsWithFutureDates();
+ //38. Find any animals assigned to an inactivated project or deactivated protocol.
+ getAnimalsWithInvalidProjectOrProtocol();
}
else if (alertType.equals("colonyManagement")) {
// 1. Find all living animals without a weight.
@@ -1356,6 +1381,83 @@ private void getProtocolsNearingAnimalLimitPercentage() {
this.protocolsNearingAnimalLimitPercentage = returnArray;
this.protocolsNearingAnimalLimitPercentageURLView = viewQueryURL;
}
+
+ // Find any animals assigned to an inactivated project or deactivated protocol.
+ ArrayList animalsWithInvalidProjectOrProtocol = new ArrayList<>(); //
+ String animalsWithInvalidProjectOrProtocolURLView;
+ private void getAnimalsWithInvalidProjectOrProtocol() {
+ // Creates filter.
+ SimpleFilter myFilter = new SimpleFilter("Id/Dataset/Demographics/calculated_status", "Alive", CompareType.EQUAL);
+// myFilter.addCondition("project/protocol", "", CompareType.NONBLANK);
+ // Gets columns to retrieve.
+ String[] targetColumns = new String[]{"id", "project", "project/protocol", "project/enddate", "project/protocol/enddate"};
+ // Runs query.
+ ArrayList> returnArray = notificationToolkit.getTableMultiRowMultiColumnWithFieldKeys(c, u, "study", "Assignment", myFilter, null, targetColumns);
+
+ // Sets up a Try/Catch block to catch date parsing errors.
+ try {
+ // Sets variables.
+ SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd");
+ Date formattedCurrentDate = myFormat.parse(dateToolkit.getCurrentTime());
+
+ for (HashMap result : returnArray) {
+ // 0: ID
+ // 1: Project
+ // 2: Project End Date
+ // 3: Protocol
+ // 4: Protocol End Date
+ String[] myCurrentRow = new String[5];
+ myCurrentRow[1] = "";
+ myCurrentRow[2] = "";
+ myCurrentRow[3] = "";
+ myCurrentRow[4] = "";
+
+ // Retrieves row data.
+ String currentID = result.get("id");
+ String currentProject = result.get("project");
+ String currentProtocol = result.get("project/protocol");
+ String currentProjectEnd = result.get("project/enddate");
+ String currentProtocolEnd = result.get("project/protocol/enddate");
+ Boolean projectOrProtocolExpired = false;
+
+ // Adds id.
+ myCurrentRow[0] = currentID;
+ // Checks project.
+ if (currentProject != null && currentProjectEnd != null) {
+ if (!currentProject.isEmpty() && !currentProjectEnd.isEmpty()) {
+ Date formattedProjectEnd = myFormat.parse(currentProjectEnd);
+ if (formattedCurrentDate.compareTo(formattedProjectEnd) > 0) {
+ myCurrentRow[1] = currentProject;
+ myCurrentRow[2] = currentProjectEnd;
+ projectOrProtocolExpired = true;
+ }
+ }
+ }
+ // Checks protocol.
+ if (currentProtocol != null && currentProtocolEnd != null) {
+ if (!currentProtocol.isEmpty() && !currentProtocolEnd.isEmpty()) {
+ Date formattedProtocolEnd = myFormat.parse(currentProtocolEnd);
+ if (formattedCurrentDate.compareTo(formattedProtocolEnd) > 0) {
+ myCurrentRow[3] = currentProtocol;
+ myCurrentRow[4] = currentProtocolEnd;
+ projectOrProtocolExpired = true;
+ }
+ }
+ }
+
+ // Adds row to return list if there is an expired project or protocol.
+ if (projectOrProtocolExpired) {
+ animalsWithInvalidProjectOrProtocol.add(myCurrentRow);
+ }
+ }
+ }
+ catch (ParseException e) {
+ _log.error("There was a parsing exception for: ColonyAlertsNotificationRevamp->getAnimalsWithInvalidProjectOrProtocol", e);
+ }
+
+ // Creates url link to the assignments table.
+ this.animalsWithInvalidProjectOrProtocolURLView = notificationToolkit.createQueryURL(c, "execute", "study", "Assignment", null);
+ }
}
}
diff --git a/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/TreatmentAlertsNotificationRevamp.java b/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/TreatmentAlertsNotificationRevamp.java
new file mode 100644
index 000000000..13412570a
--- /dev/null
+++ b/WNPRC_EHR/src/org/labkey/wnprc_ehr/notification/TreatmentAlertsNotificationRevamp.java
@@ -0,0 +1,438 @@
+package org.labkey.wnprc_ehr.notification;
+
+import org.labkey.api.data.CompareType;
+import org.labkey.api.data.Container;
+import org.labkey.api.data.SimpleFilter;
+import org.labkey.api.data.Sort;
+import org.labkey.api.module.Module;
+import org.labkey.api.security.User;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+
+public class TreatmentAlertsNotificationRevamp extends AbstractEHRNotification {
+ //Class Variables
+ NotificationToolkit notificationToolkit = new NotificationToolkit();
+ NotificationToolkit.DateToolkit dateToolkit = new NotificationToolkit.DateToolkit();
+ NotificationToolkit.StyleToolkit styleToolkit = new NotificationToolkit.StyleToolkit();
+
+
+
+
+
+ // Constructors
+ /**
+ * This constructor is used to register the notification in WNPRC_EHRModule.java.
+ * @param owner
+ */
+ public TreatmentAlertsNotificationRevamp(Module owner) {super(owner);}
+
+
+
+
+
+ // Notification Details
+ @Override
+ public String getName() {
+ return "Treatment Alerts Notification Revamp";
+ }
+ @Override
+ public String getDescription() {
+ return "This email contains any scheduled treatments not marked as completed.";
+ }
+ @Override
+ public String getEmailSubject(Container c) {
+ return "Treatment Alerts: " + dateToolkit.getCurrentTime();
+ }
+ @Override
+ public String getScheduleDescription() {
+ return "Daily at 6:00AM, 10:00AM, 1:00PM, 3:00PM, 5:00PM, 7:00PM";
+ }
+ @Override
+ public String getCronString() {
+ return notificationToolkit.createCronString("0", "6,10,13,15,17,19", "*");
+ }
+ @Override
+ public String getCategory() {
+ return "Revamped Notifications";
+ }
+
+
+
+
+
+ //Message Creation
+ @Override
+ public String getMessageBodyHTML(Container c, User u) {
+
+ // Creates variables & gets data.
+ final StringBuilder messageBody = new StringBuilder();
+ TreatmentAlertsObject myTreatmentAlertsObject = new TreatmentAlertsObject(c, u);
+
+ // Creates CSS.
+ messageBody.append(styleToolkit.beginStyle());
+ messageBody.append(styleToolkit.setBasicTableStyle());
+ messageBody.append(styleToolkit.setHeaderRowBackgroundColor("#d9d9d9"));
+ messageBody.append(styleToolkit.endStyle());
+
+ // Begins message info.
+ messageBody.append("This email contains any scheduled treatments not marked as completed. It was run on: " + dateToolkit.getCurrentTime() + ".");
+
+ // Creates message.
+ // 1. Shows all rooms lacking observations today.
+ if (!myTreatmentAlertsObject.roomsLackingObservationsToday.isEmpty()) {
+ messageBody.append("WARNING: The following rooms do not have any obs for today as of: " + dateToolkit.getCurrentTime() + ".");
+ messageBody.append("" + notificationToolkit.createHyperlink("Click here to view them.
\n", myTreatmentAlertsObject.roomsLackingObservationsTodayUrlView));
+ for (HashMap result : myTreatmentAlertsObject.roomsLackingObservationsToday) {
+ messageBody.append(result.get("room") + "
");
+ }
+ messageBody.append("
\n");
+ }
+ // 2. Shows all treatments where the animal is not assigned to that project.
+ if (!myTreatmentAlertsObject.treatmentsWithAnimalNotAssignedToProject.isEmpty()) {
+ messageBody.append("WARNING: There are " + myTreatmentAlertsObject.treatmentsWithAnimalNotAssignedToProject.size() + " scheduled treatments where the animal is not assigned to the project.
");
+ messageBody.append("" + notificationToolkit.createHyperlink("Click here to view them.
\n", myTreatmentAlertsObject.treatmentsWithAnimalNotAssignedToProjectUrlView));
+ messageBody.append("
\n");
+ }
+ // 3. Shows treatments for each time of day.
+ String[] timesOfDay = {"AM", "Noon", "PM", "Any Time", "Night"};
+ String[] treatmentColumns = new String[]{"ID", "Treatment", "Route", "Concentration", "Amount To Give", "Volume", "Instructions", "Ordered By"};
+
+ for (String timeOfDay : timesOfDay) {
+ // Verifies there are treatments scheduled.
+ 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.
\n", myTreatmentAlertsObject.treatmentsForEachTimeOfDayUrlView.get(timeOfDay)));
+
+ // Creates the current timeOfDay results sorted by (area --> room --> result).
+ HashMap>>> resultsByArea = new HashMap<>();
+
+ for (HashMap result : myTreatmentAlertsObject.incompleteTreatmentsForEachTimeOfDay.get(timeOfDay)) {
+ String currentArea = result.get("CurrentArea");
+ String currentRoom = result.get("CurrentRoom");
+ // Adds result if area does not yet exist.
+ if (!resultsByArea.containsKey(currentArea)) {
+ // Creates new treatments list.
+ ArrayList> roomTreatments = new ArrayList<>();
+ roomTreatments.add(result);
+ // Adds new treatments list to new room.
+ HashMap>> newRoom = new HashMap<>();
+ newRoom.put(currentRoom, roomTreatments);
+ // Adds new room to new area.
+ resultsByArea.put(currentArea, newRoom);
+ }
+ // Adds result if area exists but room does not yet exist.
+ else if (!resultsByArea.get(currentArea).containsKey(currentRoom)) {
+ // Creates new treatments list.
+ ArrayList> roomTreatments = new ArrayList<>();
+ roomTreatments.add(result);
+ // Adds new room to new area.
+ resultsByArea.get(currentArea).put(currentRoom, roomTreatments);
+ }
+ // Adds result if area and room both exist.
+ else {
+ resultsByArea.get(currentArea).get(currentRoom).add(result);
+ }
+ }
+
+ // Iterates through each area (sorted alphabetically).
+ for (String currentArea : notificationToolkit.sortSetWithNulls(resultsByArea.keySet())) {
+ messageBody.append("" + currentArea + ":
\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() + "
\n");
+ // Reformats the treatment hashmap into a String[] List (to be compatible with the table creation function).
+ ArrayList formattedResults = new ArrayList<>();
+ for (HashMap currentTreatment : resultsByArea.get(currentArea).get(currentRoom)) {
+ String[] newTableRow = new String[]{
+ currentTreatment.get("Id"),
+ currentTreatment.get("meaning"),
+ currentTreatment.get("route"),
+ currentTreatment.get("conc2"),
+ currentTreatment.get("amount2"),
+ currentTreatment.get("volume2"),
+ currentTreatment.get("remark"),
+ currentTreatment.get("performedby")
+ };
+ formattedResults.add(newTableRow);
+ }
+ // Displays table with results.
+ NotificationToolkit.NotificationRevampTable myTable = new NotificationToolkit.NotificationRevampTable(treatmentColumns, formattedResults);
+ messageBody.append(myTable.createBasicHTMLTable());
+ }
+ }
+
+ }
+ else {
+ messageBody.append("There are no scheduled " + timeOfDay + " treatments as of " + dateToolkit.getCurrentTime() + ". Treatments could be added after this email was sent, so please check online closer to the time.");
+ }
+ messageBody.append("
\n");
+ }
+ // 4. Shows any treatments from today that differ from the order.
+ if (!myTreatmentAlertsObject.differentOrderTreatments.isEmpty()) {
+ // Reformats the String List into a String[] List (to be compatible with the table creation function).
+ ArrayList formattedResults = new ArrayList<>();
+ for (String result : myTreatmentAlertsObject.differentOrderTreatments) {
+ formattedResults.add(new String[]{result});
+ }
+ // Creates the necessary table.
+ String[] diffTableColumns = new String[]{"DIFFERING TREATMENTS"};
+ NotificationToolkit.NotificationRevampTable myTable = new NotificationToolkit.NotificationRevampTable(diffTableColumns, formattedResults);
+ messageBody.append(myTable.createBasicHTMLTable());
+ messageBody.append("
\n");
+ }
+ // 5. Shows any treatments where the animal is not alive.
+ if (!myTreatmentAlertsObject.treatmentsWhereAnimalIsNotAlive.isEmpty()) {
+ messageBody.append("WARNING: There are " + myTreatmentAlertsObject.treatmentsWhereAnimalIsNotAlive.size() + " active treatments for animals not currently at WNPRC.");
+ messageBody.append("" + notificationToolkit.createHyperlink("Click here to view and update them.
\n", myTreatmentAlertsObject.treatmentsWhereAnimalIsNotAliveURLView));
+ messageBody.append("
\n");
+ }
+ // 6. Find any problems where the animal is not alive.
+ if (!myTreatmentAlertsObject.problemsWhereAnimalIsNotAlive.isEmpty()) {
+ messageBody.append("WARNING: There are " + myTreatmentAlertsObject.problemsWhereAnimalIsNotAlive.size() + " unresolved problems for animals not currently at WNPRC.");
+ messageBody.append("" + notificationToolkit.createHyperlink("Click here to view and update them.
\n", myTreatmentAlertsObject.problemsWhereAnimalIsNotAliveUrlView));
+ messageBody.append("
\n");
+ }
+ // 7. Checks for missing In Rooms after 2:30pm, as specified in the SOP.
+ if (!myTreatmentAlertsObject.missingInRoomsAfterTwoThirty.isEmpty()) {
+ messageBody.append("WARNING: There are " + myTreatmentAlertsObject.missingInRoomsAfterTwoThirty.size() + " " + notificationToolkit.createHyperlink("animals without In Rooms", myTreatmentAlertsObject.missingInRoomsAfterTwoThirtyUrlView) + ".");
+ }
+
+
+ return messageBody.toString();
+ }
+
+ // Gets all info for Treatment Alerts.
+ public static class TreatmentAlertsObject {
+ //Set up.
+ NotificationToolkit notificationToolkit = new NotificationToolkit();
+ NotificationToolkit.DateToolkit dateToolkit = new NotificationToolkit.DateToolkit();
+ Date todayDate = dateToolkit.getDateToday();
+
+ TreatmentAlertsObject(Container c, User u) {
+ getRoomsLackingObservationsToday(c, u);
+ getTreatmentsWithAnimalNotAssignedToProject(c, u);
+ getIncompleteTreatmentsForEachTimeOfDay(c, u);
+ getDifferentOrderTreatments(c, u);
+ getTreatmentsWhereAnimalIsNotAlive(c, u);
+ getProblemsWhereAnimalIsNotAlive(c, u);
+ getMissingInRoomsAfterTwoThirty(c, u);
+ }
+
+ // Gets any rooms lacking observations for today.
+ ArrayList> roomsLackingObservationsToday;
+ String roomsLackingObservationsTodayUrlView;
+ private void getRoomsLackingObservationsToday(Container c, User u) {
+ // Creates filter.
+ SimpleFilter myFilter = new SimpleFilter("hasObs", "N", CompareType.EQUAL);
+ // Creates columns to retrieve.
+ String[] targetColumns = new String[]{"room"};
+ // Runs query.
+ ArrayList> returnArray = notificationToolkit.getTableMultiRowMultiColumnWithFieldKeys(c, u, "ehr", "RoomsWithoutObsToday", myFilter, null, targetColumns);
+
+ // Assigns data.
+ this.roomsLackingObservationsToday = returnArray;
+ this.roomsLackingObservationsTodayUrlView = notificationToolkit.createQueryURL(c, "execute", "ehr", "RoomsWithoutObsToday", myFilter);
+ }
+
+ // Gets all treatments (today) where the animal is not assigned to that project.
+ ArrayList> treatmentsWithAnimalNotAssignedToProject;
+ String treatmentsWithAnimalNotAssignedToProjectUrlView;
+ private void getTreatmentsWithAnimalNotAssignedToProject(Container c, User u) {
+ // Creates filter.
+ SimpleFilter myFilter = new SimpleFilter("Id/DataSet/Demographics/calculated_status", "Alive", CompareType.EQUAL);
+ myFilter.addCondition("projectStatus", "", CompareType.NONBLANK);
+ myFilter.addCondition("date", todayDate, CompareType.DATE_EQUAL);
+ // Creates columns to retrieve.
+ String[] targetColumns = new String[]{"Id"};
+ // Runs query.
+ ArrayList> returnArray = notificationToolkit.getTableMultiRowMultiColumnWithFieldKeys(c, u, "study", "treatmentSchedule", myFilter, null, targetColumns);
+
+ // Assigns data.
+ this.treatmentsWithAnimalNotAssignedToProject = returnArray;
+ this.treatmentsWithAnimalNotAssignedToProjectUrlView = notificationToolkit.createQueryURL(c, "execute", "study", "treatmentSchedule", myFilter);
+ }
+
+ // Gets all treatments (today) for each time of the day (AM, Noon, PM, Any Time, Night).
+ HashMap>> incompleteTreatmentsForEachTimeOfDay = new HashMap<>() {{
+ put("AM", new ArrayList());
+ put("Noon", new ArrayList());
+ put("PM", new ArrayList());
+ put("Any Time", new ArrayList());
+ put("Night", new ArrayList());
+ }};
+ HashMap completedTreatmentCountsForEachTimeOfDay = new HashMap<>() {{
+ put("AM", 0);
+ put("Noon", 0);
+ put("PM", 0);
+ put("Any Time", 0);
+ put("Night", 0);
+ }};
+ HashMap treatmentsForEachTimeOfDayUrlView = new HashMap<>();
+ private void getIncompleteTreatmentsForEachTimeOfDay(Container c, User u) {
+ // Creates filter.
+ SimpleFilter myFilter = new SimpleFilter("Id/DataSet/Demographics/calculated_status", "Alive", CompareType.EQUAL);
+ myFilter.addCondition("date", todayDate, CompareType.DATE_EQUAL);
+ // Creates sort.
+ Sort mySort = new Sort("CurrentArea,CurrentRoom");
+ // Creates columns to retrieve.
+ String[] targetColumns = new String[]{"timeofday", "Id", "CurrentArea", "CurrentRoom", "CurrentCage", "projectStatus", "treatmentStatus", "treatmentStatus/Label", "meaning", "code", "volume2", "conc2", "route", "amount2", "remark", "performedby"};
+ // Runs query.
+ ArrayList> returnArray = notificationToolkit.getTableMultiRowMultiColumnWithFieldKeys(c, u, "study", "treatmentSchedule", myFilter, mySort, targetColumns);
+
+ if (!returnArray.isEmpty()) {
+ // Sorts data for each time of day.
+ for (HashMap currentTreatment : returnArray) {
+ String treatmentTime = currentTreatment.get("timeofday");
+ // Verifies time of day is one of the 5 supported times.
+ if (treatmentTime != null) {
+ if (treatmentTime.equals("AM") || treatmentTime.equals("Noon") || treatmentTime.equals("PM") || treatmentTime.equals("Any Time") || treatmentTime.equals("Night")) {
+ if (currentTreatment.get("treatmentStatus/Label").equals("Completed")) {
+ Integer currentCount = completedTreatmentCountsForEachTimeOfDay.get(treatmentTime);
+ completedTreatmentCountsForEachTimeOfDay.put(treatmentTime, currentCount + 1);
+ }
+ else {
+ incompleteTreatmentsForEachTimeOfDay.get(treatmentTime).add(currentTreatment);
+ }
+ }
+ }
+ }
+ // Updates official class variable for each time of day's URL view.
+ SimpleFilter amFilter = new SimpleFilter(myFilter);
+ SimpleFilter noonFilter = new SimpleFilter(myFilter);
+ SimpleFilter pmFilter = new SimpleFilter(myFilter);
+ SimpleFilter anytimeFilter = new SimpleFilter(myFilter);
+ SimpleFilter nightFilter = new SimpleFilter(myFilter);
+ amFilter.addCondition("timeofday", "AM", CompareType.EQUAL);
+ noonFilter.addCondition("timeofday", "Noon", CompareType.EQUAL);
+ pmFilter.addCondition("timeofday", "PM", CompareType.EQUAL);
+ anytimeFilter.addCondition("timeofday", "Any Time", CompareType.EQUAL);
+ nightFilter.addCondition("timeofday", "Night", CompareType.EQUAL);
+ this.treatmentsForEachTimeOfDayUrlView.put("AM", notificationToolkit.createQueryURL(c, "execute", "study", "treatmentSchedule", amFilter));
+ this.treatmentsForEachTimeOfDayUrlView.put("Noon", notificationToolkit.createQueryURL(c, "execute", "study", "treatmentSchedule", noonFilter));
+ this.treatmentsForEachTimeOfDayUrlView.put("PM", notificationToolkit.createQueryURL(c, "execute", "study", "treatmentSchedule", pmFilter));
+ this.treatmentsForEachTimeOfDayUrlView.put("Any Time", notificationToolkit.createQueryURL(c, "execute", "study", "treatmentSchedule", anytimeFilter));
+ this.treatmentsForEachTimeOfDayUrlView.put("Night", notificationToolkit.createQueryURL(c, "execute", "study", "treatmentSchedule", nightFilter));
+ }
+ }
+
+ // Gets all treatments (today) that differ from the order.
+ List differentOrderTreatments;
+ String differentOrderTreatmentsUrlView;
+ private void getDifferentOrderTreatments(Container c, User u) {
+ // Creates variable.
+ List resultsAsTableEntries = new ArrayList<>();
+ // Creates filter.
+ SimpleFilter myFilter = new SimpleFilter("date", todayDate, CompareType.DATE_EQUAL);
+ // Creates columns to retrieve.
+ String[] targetColumns = new String[]{"CurrentArea", "CurrentRoom", "id", "date", "meaning", "performedby", "drug_performedby", "route", "drug_route", "concentration", "drug_concentration", "conc_units", "drug_conc_units", "dosage", "drug_dosage", "dosage_units", "drug_dosage_units", "amount", "drug_amount", "amount_units", "drug_amount_units", "volume", "drug_volume", "vol_units", "drug_vol_units"};
+ // Runs query.
+ ArrayList> returnArray = notificationToolkit.getTableMultiRowMultiColumnWithFieldKeys(c, u, "study", "TreatmentsThatDiffer", myFilter, null, targetColumns);
+
+ for (HashMap currentTreatment : returnArray) {
+ // Creates variable.
+ StringBuilder currentTableEntry = new StringBuilder();
+
+ // Displays the basic info for the current treatment.
+ currentTableEntry.append("Id: " + currentTreatment.get("id") + "
\n");
+ currentTableEntry.append("Date: " + currentTreatment.get("date") + "
\n");
+ currentTableEntry.append("Treatment: " + currentTreatment.get("meaning") + "
\n");
+ currentTableEntry.append("Ordered By: " + currentTreatment.get("performedby") + "
\n");
+ currentTableEntry.append("Performed By: " + currentTreatment.get("drug_performedby") + "
\n");
+
+ // Displays which order/entry field in the treatment does not match.
+ // Compares the route.
+ if (!currentTreatment.get("route").equals(currentTreatment.get("drug_route"))) {
+ currentTableEntry.append("Route Ordered: " + currentTreatment.get("route") + "
\n");
+ currentTableEntry.append("Route Entered: " + currentTreatment.get("drug_route") + "
\n");
+ }
+ // Compares the concentration & concentration units.
+ if (!currentTreatment.get("concentration").equals(currentTreatment.get("drug_concentration")) || !currentTreatment.get("conc_units").equals(currentTreatment.get("drug_conc_units"))) {
+ currentTableEntry.append("Concentration Ordered: " + currentTreatment.get("concentration") + " " + currentTreatment.get("conc_units") + "
\n");
+ currentTableEntry.append("Concentration Entered: " + currentTreatment.get("drug_concentration") + " " + currentTreatment.get("drug_conc_units") + "
\n");
+ }
+ // Compares the dosage & dosage units.
+ if (!currentTreatment.get("dosage").equals(currentTreatment.get("drug_dosage")) || !currentTreatment.get("dosage_units").equals(currentTreatment.get("drug_dosage_units"))) {
+ currentTableEntry.append("Dosage Ordered: " + currentTreatment.get("dosage") + " " + currentTreatment.get("dosage_units") + "
\n");
+ currentTableEntry.append("Dosage Entered: " + currentTreatment.get("drug_dosage") + " " + currentTreatment.get("drug_dosage_units") + "
\n");
+ }
+ // Compares the amount & amount units.
+ if (!currentTreatment.get("amount").equals(currentTreatment.get("drug_amount")) || !currentTreatment.get("amount_units").equals(currentTreatment.get("drug_amount_units"))) {
+ currentTableEntry.append("Amount Ordered: " + currentTreatment.get("amount") + " " + currentTreatment.get("amount_units") + "
\n");
+ currentTableEntry.append("Amount Entered: " + currentTreatment.get("drug_amount") + " " + currentTreatment.get("drug_amount_units") + "
\n");
+ }
+ // Compares the volume & volume units.
+ if (!currentTreatment.get("volume").equals(currentTreatment.get("drug_volume")) || !currentTreatment.get("vol_units").equals(currentTreatment.get("drug_vol_units"))) {
+ currentTableEntry.append("Volume Ordered: " + currentTreatment.get("volume") + " " + currentTreatment.get("vol_units") + "
\n");
+ currentTableEntry.append("Volume Entered: " + currentTreatment.get("drug_volume") + " " + currentTreatment.get("drug_vol_units") + "
\n");
+ }
+
+ // Adds treatment to table row list.
+ resultsAsTableEntries.add(currentTableEntry.toString());
+ }
+
+ // Assigns data.
+ this.differentOrderTreatments = resultsAsTableEntries;
+ this.differentOrderTreatmentsUrlView = notificationToolkit.createQueryURL(c, "execute", "study", "TreatmentsThatDiffer", myFilter);
+ }
+
+ // Gets all treatments (today & future) where the animal is not alive.
+ ArrayList> treatmentsWhereAnimalIsNotAlive;
+ String treatmentsWhereAnimalIsNotAliveURLView;
+ private void getTreatmentsWhereAnimalIsNotAlive(Container c, User u) {
+ // Creates filter.
+ SimpleFilter myFilter = new SimpleFilter("Id/DataSet/Demographics/calculated_status", "Alive", CompareType.NEQ_OR_NULL);
+ myFilter.addCondition("enddate", "", CompareType.ISBLANK);
+ // Creates columns to retrieve.
+ String[] targetColumns = new String[]{"Id"};
+ // Runs query.
+ ArrayList> returnArray = notificationToolkit.getTableMultiRowMultiColumnWithFieldKeys(c, u, "study", "Treatment Orders", myFilter, null, targetColumns);
+
+ // Assigns data.
+ this.treatmentsWhereAnimalIsNotAlive = returnArray;
+ this.treatmentsWhereAnimalIsNotAliveURLView = notificationToolkit.createQueryURL(c, "execute", "study", "Treatment Orders", myFilter);
+ }
+
+ // Gets any problems (today & future) where the animal is not alive.
+ ArrayList> problemsWhereAnimalIsNotAlive;
+ String problemsWhereAnimalIsNotAliveUrlView;
+ private void getProblemsWhereAnimalIsNotAlive(Container c, User u) {
+ // Creates filter.
+ SimpleFilter myFilter = new SimpleFilter("Id/DataSet/Demographics/calculated_status", "Alive", CompareType.NEQ_OR_NULL);
+ myFilter.addCondition("enddate", "", CompareType.ISBLANK);
+ // Creates columns to retrieve.
+ String[] targetColumns = new String[]{"Id"};
+ // Runs query.
+ ArrayList> returnArray = notificationToolkit.getTableMultiRowMultiColumnWithFieldKeys(c, u, "study", "Problem List", myFilter, null, targetColumns);
+
+ // Assigns data.
+ this.problemsWhereAnimalIsNotAlive = returnArray;
+ this.problemsWhereAnimalIsNotAliveUrlView = notificationToolkit.createQueryURL(c, "execute", "study", "Problem List", myFilter);
+ }
+
+ // Checks for missing-in-rooms after 2:30pm, as specified in the SOP.
+ ArrayList> missingInRoomsAfterTwoThirty;
+ String missingInRoomsAfterTwoThirtyUrlView;
+ private void getMissingInRoomsAfterTwoThirty(Container c, User u) {
+ // Creates columns to retrieve.
+ String[] targetColumns = new String[]{"Id"};
+ // Runs query.
+ ArrayList> returnArray = notificationToolkit.getTableMultiRowMultiColumnWithFieldKeys(c, u, "study", "inRoomNotSubmitted", null, null, targetColumns);
+
+ // Assigns data.
+ this.missingInRoomsAfterTwoThirty = returnArray;
+ this.missingInRoomsAfterTwoThirtyUrlView = notificationToolkit.createQueryURL(c, "execute", "study", "inRoomNotSubmitted", null);
+ }
+
+
+
+
+
+
+ }
+
+}