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); + } + + + + + + + } + +}