diff --git a/onprc_ehr/resources/queries/study/TattooAlert.sql b/onprc_ehr/resources/queries/study/TattooAlert.sql
new file mode 100644
index 000000000..46018da83
--- /dev/null
+++ b/onprc_ehr/resources/queries/study/TattooAlert.sql
@@ -0,0 +1,5 @@
+-- Displays all animals with tattoo procedure missing in the encounters table. Excluding the purchased animals
+Select Id, birth, gender from study.demographics a
+Where a.calculated_status = 'Alive'
+ And a.id not in (Select id from study.arrival where acquisitiontype = 6) --6= Purchase
+ And a.id not in (Select id from study.encounters where procedureid = 760) -- TATTOO procedure
\ No newline at end of file
diff --git a/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js b/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js
index 6781fe524..4cb521606 100644
--- a/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js
+++ b/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js
@@ -721,6 +721,15 @@ exports.init = function(EHR){
}
});
+ //Added: By Kollil on 5/31/2022
+ //When the Tattoo procedure is selected, add snomedcode: P-12090 TATTOOING
+ EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.AFTER_UPSERT, 'study', 'encounters', function(helper, errors, row, oldRow){
+ if (row.procedureid == 760){
+ //Add snomed code.
+ triggerHelper.addTattooSnomedCode(row.Id, row);
+ }
+ });
+
EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'drug', function(helper, scriptErrors, row, oldRow){
if (row.outcome && row.outcome != 'Normal' && !row.remark){
EHR.Server.Utils.addError(scriptErrors, 'remark', 'A remark is required if a non-normal outcome is reported', 'WARN');
diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/notification/ClinicalRoundsNotification.java b/onprc_ehr/src/org/labkey/onprc_ehr/notification/ClinicalRoundsNotification.java
index 2c719c49d..e1324b62b 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/notification/ClinicalRoundsNotification.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/notification/ClinicalRoundsNotification.java
@@ -62,21 +62,27 @@ public String getEmailSubject(Container c)
}
@Override
+// public String getCronString()
+// {
+// return "0 0 15 * * ?";
+// }
+
+ //Kollil 10/13: Changed the daily alert to Tuesdays and Thursdays
public String getCronString()
{
- return "0 0 15 * * ?";
+ return "0 0 15 ? * TUE,THU";
}
@Override
public String getScheduleDescription()
{
- return "every day at 3PM";
+ return "every Tuesday & Thursday at 3PM";
}
@Override
public String getDescription()
{
- return "The report is designed alert if there are any animals without rounds observations entered or lacking vet review";
+ return "The report is designed to alert if there are any animals without rounds observations entered or lacking vet review. Also, contains the report to alert for Clinical rounds observations entered today, and not entered recently";
}
@Override
@@ -86,7 +92,11 @@ public String getMessageBodyHTML(Container c, User u)
duplicateCases(c, u, msg);
animalsWithoutRounds(c, u, msg);
- //animalsWithoutVetReview(c, u, msg);
+ animalsWithoutVetReview(c, u, msg);
+
+ //Clinical process alerts : Kollil, 10/13/22
+ animalsWithRounds(c, u, msg); //Added: 8-22-2016 R.Blasa
+ //animalsWithoutRounds2(c, u, msg); //Added 8-29-2016
return msg.toString();
}
@@ -112,7 +122,8 @@ protected void animalsWithoutRounds(final Container c, User u, final StringBuild
long count = ts.getRowCount();
if (count > 0)
{
- msg.append("WARNING: There are " + count + " active cases that do not have obs entered today.
");
+ msg.append("Clinical Rounds Alerts: Active cases that do not have observations.
");
+ msg.append("WARNING: " + count + " active case(s) found that do not have obs entered today.
");
msg.append("
");
msg.append("Room | Cage | Id | Assigned Vet | Problem(s) | Days Since Last Rounds |
");
@@ -163,7 +174,8 @@ protected void animalsWithoutVetReview(final Container c, User u, final StringBu
long count = ts.getRowCount();
if (count > 0)
{
- msg.append("WARNING: There are " + count + " active cases that have not been vet reviewed in the past 7 days.
");
+ msg.append("Clinical Rounds Alerts: Active cases with no Vet review.
");
+ msg.append("WARNING: " + count + " active case(s) found that have not been vet reviewed in the past 7 days.
");
msg.append("");
msg.append("Room | Cage | Id | Assigned Vet | Problem(s) | Days Since last Vet Review |
");
@@ -188,4 +200,108 @@ public void exec(ResultSet object) throws SQLException
msg.append("
\n");
}
}
-}
+
+ //Clinical process alerts
+//
+
+ //Modified: 8-15-2016 R.Blasa Show Clinical open cases that were entered
+ protected void animalsWithRounds(final Container c, User u, final StringBuilder msg)
+ {
+ SimpleFilter filter = new SimpleFilter(FieldKey.fromString("daysSinceLastRounds"), 0, CompareType.EQUAL);
+ filter.addCondition(FieldKey.fromString("isActive"), true, CompareType.EQUAL);
+ filter.addCondition(FieldKey.fromString("category"), "Clinical", CompareType.EQUAL);
+ filter.addCondition(FieldKey.fromString("Id/demographics/calculated_status"), "Alive", CompareType.EQUAL);
+
+ TableInfo ti = getStudySchema(c, u).getTable("cases");
+ Set keys = new HashSet<>();
+ keys.add(FieldKey.fromString("Id"));
+ keys.add(FieldKey.fromString("Id/curLocation/room"));
+ keys.add(FieldKey.fromString("Id/curLocation/cage"));
+ keys.add(FieldKey.fromString("daysSinceLastRounds"));
+ keys.add(FieldKey.fromString("assignedvet/DisplayName"));
+ keys.add(FieldKey.fromString("allProblemCategories"));
+ final Map cols = QueryService.get().getColumns(ti, keys);
+
+ TableSelector ts = new TableSelector(ti, cols.values(), filter, new Sort("Id/curLocation/room_sortValue,Id/curLocation/cage_sortValue"));
+ long count = ts.getRowCount();
+
+ if (count > 0)
+ {
+ msg.append("Clinical Rounds Process Alerts: Active cases that have observations.
");
+ msg.append("CONFIRMATION: " + count + " active case(s) found that have their obs entered today.
");
+ msg.append("");
+ msg.append("Room | Cage | Id | Assigned Vet | Problem(s) |
");
+
+ ts.forEach(new Selector.ForEachBlock()
+ {
+ @Override
+ public void exec(ResultSet object) throws SQLException
+ {
+ Results rs = new ResultsImpl(object, cols);
+ msg.append("");
+ msg.append("" + safeAppend(rs.getString(FieldKey.fromString("Id/curLocation/room")), "None") + " | ");
+ msg.append("" + safeAppend(rs.getString(FieldKey.fromString("Id/curLocation/cage")), "") + " | ");
+ msg.append("" + rs.getString(FieldKey.fromString("Id")) + " | ");
+ msg.append("" + safeAppend(rs.getString(FieldKey.fromString("assignedvet/DisplayName")), "None") + " | ");
+ msg.append("" + safeAppend(rs.getString(FieldKey.fromString("allProblemCategories")), "None") + " | ");
+
+ msg.append("
");
+ }
+ });
+
+ msg.append("
");
+ msg.append("
\n");
+ }
+ }
+
+
+ // protected void animalsWithoutRounds2(final Container c, User u, final StringBuilder msg)
+// {
+// SimpleFilter filter = new SimpleFilter(FieldKey.fromString("daysSinceLastRounds"), 0, CompareType.GT);
+// filter.addCondition(FieldKey.fromString("isActive"), true, CompareType.EQUAL);
+// filter.addCondition(FieldKey.fromString("category"), "Clinical", CompareType.EQUAL);
+// filter.addCondition(FieldKey.fromString("Id/demographics/calculated_status"), "Alive", CompareType.EQUAL);
+//
+// TableInfo ti = getStudySchema(c, u).getTable("cases");
+// Set keys = new HashSet<>();
+// keys.add(FieldKey.fromString("Id"));
+// keys.add(FieldKey.fromString("Id/curLocation/room"));
+// keys.add(FieldKey.fromString("Id/curLocation/cage"));
+// keys.add(FieldKey.fromString("daysSinceLastRounds"));
+// keys.add(FieldKey.fromString("assignedvet/DisplayName"));
+// keys.add(FieldKey.fromString("allProblemCategories"));
+// final Map cols = QueryService.get().getColumns(ti, keys);
+//
+// TableSelector ts = new TableSelector(ti, cols.values(), filter, new Sort("Id/curLocation/room_sortValue,Id/curLocation/cage_sortValue"));
+// long count = ts.getRowCount();
+//
+// if (count > 0)
+// {
+// msg.append("Clinical Rounds Process Alerts: Active cases that do not have observations entered today.
");
+// msg.append("WARNING: There are " + count + " active cases that do not have obs entered today.
");
+// msg.append("");
+// msg.append("Room | Cage | Id | Assigned Vet | Problem(s) | Days Since Last Rounds |
");
+//
+// ts.forEach(new Selector.ForEachBlock()
+// {
+// @Override
+// public void exec(ResultSet object) throws SQLException
+// {
+// Results rs = new ResultsImpl(object, cols);
+// msg.append("");
+// msg.append("" + safeAppend(rs.getString(FieldKey.fromString("Id/curLocation/room")), "None") + " | ");
+// msg.append("" + safeAppend(rs.getString(FieldKey.fromString("Id/curLocation/cage")), "") + " | ");
+// msg.append("" + rs.getString(FieldKey.fromString("Id")) + " | ");
+// msg.append("" + safeAppend(rs.getString(FieldKey.fromString("assignedvet/DisplayName")), "None") + " | ");
+// msg.append("" + safeAppend(rs.getString(FieldKey.fromString("allProblemCategories")), "None") + " | ");
+// msg.append("" + safeAppend(rs.getString(FieldKey.fromString("daysSinceLastRounds")), "") + " | ");
+// msg.append("
");
+// }
+// });
+//
+// msg.append("
");
+// msg.append("
\n");
+// }
+// }
+
+ }
diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/notification/RoutineClinicalTestsNotification.java b/onprc_ehr/src/org/labkey/onprc_ehr/notification/RoutineClinicalTestsNotification.java
index e3ccb637a..66359d2ab 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/notification/RoutineClinicalTestsNotification.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/notification/RoutineClinicalTestsNotification.java
@@ -18,6 +18,7 @@
import org.labkey.api.data.ColumnInfo;
import org.labkey.api.data.CompareType;
import org.labkey.api.data.Container;
+import org.labkey.api.data.ContainerFilter;
import org.labkey.api.data.ResultsImpl;
import org.labkey.api.data.Selector;
import org.labkey.api.data.SimpleFilter;
@@ -92,8 +93,7 @@ public String getMessageBodyHTML(Container c, User u)
getTbAlerts(sb, c, u);
getPEAlerts(sb, c, u);
getAnimalsNotWeightedInPast60Days(sb, c, u);
-
- //getVirologyAlerts(sb, c, u);
+ getTattooAlerts(sb, c, u);
return sb.toString();
}
@@ -295,4 +295,47 @@ protected void getAnimalsNotWeightedInPast60Days(StringBuilder msg, Container c,
msg.append("
\n");
}
+
+ /**
+ * Kollil, 6/01/22 : List the animalIds with missing Tattoos, i.e, Animals with no Tattoo procedure, ProcedureId = 760
+ */
+ protected void getTattooAlerts(StringBuilder msg, Container c, User u)
+ {
+ msg.append("Animals with missing Tattoo procedure:
\n");
+
+ if (QueryService.get().getUserSchema(u, c, "study") == null) {
+ msg.append("Warning: The study schema has not been enabled in this folder, so the alert cannot run!
");
+ return;
+ }
+ //Tattoo query
+ TableInfo ti = QueryService.get().getUserSchema(u, c, "study").getTable("TattooAlert", ContainerFilter.Type.AllFolders.create(c, u));
+ Set cols = appendLocationCols(ti);
+ TableSelector ts = new TableSelector(ti, cols, null, null);
+ long count = ts.getRowCount();
+
+ //Get num of rows
+ if (count > 0)
+ {
+ msg.append("ALERT: " + count + " animals found with no Tattoo procedure recorded in Prime:");
+ //String url = getExecuteQueryUrl(c, "study", "Demographics", "By Location") + "&query.Id/MostRecentWeight/DaysSinceWeight~gt=75&query.calculated_status~eq=Alive&query.Id/curLocation/Room/housingType/value~eq=Cage Location";
+ String url = getExecuteQueryUrl(c, "study", "TattooAlert", null) + "&query.containerFilterName=AllFolders";
+ msg.append("Click here to view them.
\n");
+
+ msg.append("Summary by area:
\n");
+ msg.append("");
+ Map areaMap = getAreaMap(ts, cols);
+ for (String area : areaMap.keySet())
+ {
+ String newUrl = url + "&query.Id/curLocation/area~eq=" + area;
+ msg.append("" + area + ": | " + areaMap.get(area) + " |
\n");
+ }
+ msg.append("
");
+ msg.append("
");
+ }
+ else
+ {
+ msg.append(" All live animals at the center are tattooed! ");
+ }
+ msg.append("
\n");
+ }
}
diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/notification/VetReviewNotification.java b/onprc_ehr/src/org/labkey/onprc_ehr/notification/VetReviewNotification.java
index 3e30b8c7e..e454b213d 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/notification/VetReviewNotification.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/notification/VetReviewNotification.java
@@ -63,15 +63,20 @@ public String getEmailSubject(Container c)
}
@Override
+// public String getCronString()
+// {
+// return "0 0 15 * * ?";
+// }
+ //Kollil 10/13: Changed the daily alert to once a week, Wednesdays
public String getCronString()
{
- return "0 0 15 * * ?";
+ return "0 0 15 ? * WED";
}
@Override
public String getScheduleDescription()
{
- return "daily at 3PM";
+ return "every Wednesday at 3PM";
}
@Override
diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/query/ONPRC_EHRTriggerHelper.java b/onprc_ehr/src/org/labkey/onprc_ehr/query/ONPRC_EHRTriggerHelper.java
index d70ffb5d5..ca58d900a 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/query/ONPRC_EHRTriggerHelper.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/query/ONPRC_EHRTriggerHelper.java
@@ -185,7 +185,8 @@ public Map getExtraContext()
return map;
}
- //Added by Kolli 3/3/20
+
+ //Added by Kolli 3/3/20
//This function automatically sets the study details endDate if previous study details endDate is empty when a new study is created.
public void closeStudyDetailsRecords(List