diff --git a/onprc_ehr/resources/queries/study/ParentageDamMismatch.query.xml b/onprc_ehr/resources/queries/study/ParentageDamMismatch.query.xml new file mode 100644 index 000000000..5a237c10e --- /dev/null +++ b/onprc_ehr/resources/queries/study/ParentageDamMismatch.query.xml @@ -0,0 +1,9 @@ + + + + + Mismatched Genetic and Observed Dams +
+
+
+
\ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/ParentageDamMismatch.sql b/onprc_ehr/resources/queries/study/ParentageDamMismatch.sql new file mode 100644 index 000000000..f9e07f467 --- /dev/null +++ b/onprc_ehr/resources/queries/study/ParentageDamMismatch.sql @@ -0,0 +1,61 @@ +/* + Added by Kolli, Feb 2026 + Refer tkt# 14114 for details + Display 4 columns: Animal Id, Area, Genetic dam, Observed dam + + Get genetic and observed dam mismatch data. + Use the following criteria, + * 1. One genetic dam per animal + * 2. Included Alive + Dead animals + * 3. Excludes animals that have a foster dam + * 4. Excludes rows where observedDam or geneticDam IS BLANK + * 5. Keeps only mismatches between observed and genetic dams + * 6. Excludes old parentage entries, enddate IS BLANK +*/ + +SELECT + d.Id, + d.Id.curLocation.area AS Area, + coalesce(p2.parent, '') as geneticDam, + coalesce(b.dam, '') as observedDam +FROM study.demographics d + + LEFT JOIN ( + SELECT + p2.Id, + MAX(p2.parent) AS parent + FROM study.parentage p2 + WHERE (p2.method = 'Genetic' OR p2.method = 'Provisional Genetic') + AND p2.relationship = 'Dam' + AND p2.enddate IS NULL + GROUP BY p2.Id +) p2 ON d.Id = p2.Id + + LEFT JOIN ( + SELECT + p3.Id, + MAX(p3.parent) AS parent + FROM study.parentage p3 + WHERE p3.relationship = 'Foster Dam' + AND p3.enddate IS NULL + GROUP BY p3.Id +) p3 ON d.Id = p3.Id + + LEFT JOIN study.birth b + ON b.Id = d.Id + +WHERE d.calculated_status.code IN ('Alive', 'Dead') AND d.qcstate = 18 + /* exclude foster-dam cases (NULL or blank only) */ + AND COALESCE(RTRIM(LTRIM(CAST(p3.parent AS VARCHAR(50)))), '') = '' + + /* exclude blank observed dam */ + AND COALESCE(RTRIM(LTRIM(CAST(b.dam AS VARCHAR(50)))), '') <> '' + + /* exclude blank genetic dam */ + AND COALESCE(RTRIM(LTRIM(CAST(p2.parent AS VARCHAR(50)))), '') <> '' + + /* mismatch observed vs genetic */ + AND COALESCE(RTRIM(LTRIM(CAST(b.dam AS VARCHAR(50)))), '') <> + COALESCE(RTRIM(LTRIM(CAST(p2.parent AS VARCHAR(50)))), '') + + diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/notification/ColonyAlertsNotification.java b/onprc_ehr/src/org/labkey/onprc_ehr/notification/ColonyAlertsNotification.java index 8a5363df3..3b62bd188 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/notification/ColonyAlertsNotification.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/notification/ColonyAlertsNotification.java @@ -312,6 +312,70 @@ protected void roomsReportingNegativeCagesAvailable(final Container c, User u, f } } + /** + * Kollil, Jan, 2026 : + * Refer tkt# 14114 for more details + * Alert title: WARNING: There are [x total] mismatches of observed and genetic dam data requiring review + * Format: Table + * 4 columns: Animal Id, Area, Genetic dam, Observed dam + * Alert criteria: + * 1. One genetic dam per animal + * 2. Included Alive + Dead animals + * 3. Excludes animals that have a foster dam + * 4. Excludes rows where observedDam or geneticDam IS BLANK + * 5. Keeps only mismatches between observed and genetic dams + * 6. Excludes old parentage entries, enddate IS BLANK + */ + protected void mismatchedObservedAndGeneticDam(final Container c, User u, final StringBuilder msg) + { + 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; + } + + //Dam mismatch query + TableInfo ti = QueryService.get().getUserSchema(u, c, "study").getTable("ParentageDamMismatch", ContainerFilter.Type.AllFolders.create(c, u)); + TableSelector ts = new TableSelector(ti, null, null); + long count = ts.getRowCount(); + + //Get num of rows + if (count > 0) { + msg.append(" WARNING: There are " + count + " mismatches of observed and genetic dam data requiring review."); + msg.append(" Click here to view them in a grid\n"); + + //Display the report in the email + Set columns = new HashSet<>(); + columns.add(FieldKey.fromString("Id")); + columns.add(FieldKey.fromString("area")); + columns.add(FieldKey.fromString("geneticdam")); + columns.add(FieldKey.fromString("observeddam")); + + final Map colMap = QueryService.get().getColumns(ti, columns); + TableSelector ts2 = new TableSelector(ti, colMap.values(), null, null); + + msg.append("

\n"); + msg.append(""); + msg.append(""); + msg.append(""); + + ts2.forEach(object -> { + Results rs = new ResultsImpl(object, colMap); + String url = getParticipantURL(c, rs.getString("Id")); + msg.append("\n"); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + }); + } + else { + msg.append(" There are NO mismatches of observed and genetic dam data. "); + } + msg.append("
Id Area Genetic Dam Observed Dam
" + PageFlowUtil.filter(rs.getString("Id")) + " " + PageFlowUtil.filter(rs.getString("area")) + "" + PageFlowUtil.filter(rs.getString("geneticdam")) + "" + PageFlowUtil.filter(rs.getString("observeddam")) + "
"); + msg.append("
\n"); + } + //End of Dam mismatch report + /** * Finds all rooms with animals of mixed viral status * Modified by Kollil, 2/17/2023 diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/notification/ColonyMgmtNotification.java b/onprc_ehr/src/org/labkey/onprc_ehr/notification/ColonyMgmtNotification.java index c7d35ab92..1ca060cad 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/notification/ColonyMgmtNotification.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/notification/ColonyMgmtNotification.java @@ -74,6 +74,10 @@ public String getMessageBodyHTML(Container c, User u) doHousingChecks(c, u, msg); transfersYesterday(c, u, msg); roomsWithMixedViralStatus(c, u, msg); + /*Added by kollil, Jan, 2026 + Refer to tkt # 14114 + */ + mismatchedObservedAndGeneticDam(c, u, msg); livingAnimalsWithoutWeight(c, u, msg); hospitalAnimalsWithoutCase(c, u, msg);