diff --git a/.gitignore b/.gitignore
index eddec8274..f3a7df325 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,8 +26,6 @@ wnprc_billing/resources/credits/jars.txt
.storybook-out/
-docker/ehrcron/scripts/pg_backup/lkbackup.ini
-
# generated artifacts from @labkey/build
*/resources/web/*/gen/
*/resources/views/gen/
diff --git a/DBUtils/resources/credits/jars.txt b/DBUtils/resources/credits/jars.txt
index f6131df2d..51c096f68 100644
--- a/DBUtils/resources/credits/jars.txt
+++ b/DBUtils/resources/credits/jars.txt
@@ -1,5 +1,5 @@
{table}
-Filename|Component|Version|Source|License|LabKey Dev|Purpose
+Filename|Component|Version|Source|License|Dev|Purpose
jooq-3.8.4.jar|jOOQ|3.8.4|{link:From GitHub|https://github.com/jOOQ/jOOQ}|{link:Apache Software License 2.0|http://www.apache.org/licenses/LICENSE-2.0}|jrichardson|Database-mapping for Java
jaxb-api-2.3.0.jar|jaxb|2.3.0|Oracle|{link:CDDL 1.1|https://oss.oracle.com/licenses/CDDL+GPL-1.1}{link:GPL2w/ CPE|https://oss.oracle.com/licenses/CDDL+GPL-1.1}|klum|Parsing XML
{table}
diff --git a/DeviceProxy/resources/credits/jars.txt b/DeviceProxy/resources/credits/jars.txt
index 988c499c1..1376d436d 100644
--- a/DeviceProxy/resources/credits/jars.txt
+++ b/DeviceProxy/resources/credits/jars.txt
@@ -1,5 +1,5 @@
{table}
-Filename|Component|Version|Source|License|LabKey Dev|Purpose
+Filename|Component|Version|Source|License|Dev|Purpose
jooq-3.8.4.jar|jOOQ|3.8.4|{link:From GitHub|https://github.com/jOOQ/jOOQ}|{link:Apache Software License 2.0|http://www.apache.org/licenses/LICENSE-2.0}|jrichardson|Database-mapping for Java
jaxb-api-2.3.0.jar|Java Architecture for XML Binding (JAXB)|2.3.0|Oracle|{link:CDDL|https://oss.oracle.com/licenses/CDDL}|klum|Parsing XML
{table}
diff --git a/GoogleDrive/resources/credits/jars.txt b/GoogleDrive/resources/credits/jars.txt
index e8e8a135f..d52b3bf51 100644
--- a/GoogleDrive/resources/credits/jars.txt
+++ b/GoogleDrive/resources/credits/jars.txt
@@ -1,5 +1,5 @@
{table}
-Filename|Component|Version|Source|License|LabKey Dev|Purpose
-google-api-client-1.22.0.jar|Google APIs Client Library for Java|1.22.0|{link:From GitHub|https://github.com/google/google-api-java-client}|{link:Apache Software License 2.0|http://www.apache.org/licenses/LICENSE-2.0}|jrichardson|Used to connect to Google Drive
+Filename|Component|Version|Source|License|WNPRC Dev|Purpose
+google-api-client-1.23.0.jar|Google APIs Client Library for Java|1.23.0|{link:From GitHub|https://github.com/google/google-api-java-client}|{link:Apache Software License 2.0|http://www.apache.org/licenses/LICENSE-2.0}|jrichardson|Used to connect to Google Drive
google-api-services-drive-v3-rev85-1.23.0.jar|Google Drive API Client Library for Java|v3 rev85 1.23.0|{link:From Google|https://developers.google.com/api-client-library/java/apis/drive/v3}|{link:Apache Software License 2.0|http://www.apache.org/licenses/LICENSE-2.0}|jrichardson|Used to connect to Google Drive
{table}
\ No newline at end of file
diff --git a/WNPRC_Compliance/module.properties b/WNPRC_Compliance/module.properties
index 8378dbcc8..97cb3c7ae 100644
--- a/WNPRC_Compliance/module.properties
+++ b/WNPRC_Compliance/module.properties
@@ -4,6 +4,6 @@ License: Apache 2.0
LicenseURL: http://www.apache.org/licenses/LICENSE-2.0
ModuleClass: org.labkey.wnprc_compliance.WNPRC_ComplianceModule
Name: WNPRC_Compliance
-SchemaVersion: 20.000
+SchemaVersion: 21.001
SupportedDatabases: pgsql
ManageVersion: false
diff --git a/WNPRC_Compliance/resources/schemas/dbscripts/postgresql/wnprc_compliance-21.000-21.001.sql b/WNPRC_Compliance/resources/schemas/dbscripts/postgresql/wnprc_compliance-21.000-21.001.sql
new file mode 100644
index 000000000..d5d6eef94
--- /dev/null
+++ b/WNPRC_Compliance/resources/schemas/dbscripts/postgresql/wnprc_compliance-21.000-21.001.sql
@@ -0,0 +1,5 @@
+ALTER TABLE wnprc_compliance.measles_clearances ADD COLUMN IF NOT EXISTS required BOOLEAN DEFAULT true;
+
+ALTER TABLE wnprc_compliance.persons ADD COLUMN IF NOT EXISTS hold BOOLEAN DEFAULT false;
+--update measles_required from wnprc_compliance.measles_clearances using labkey javascript API
+ALTER TABLE wnprc_compliance.persons ADD COLUMN IF NOT EXISTS measles_required BOOLEAN DEFAULT false;
diff --git a/WNPRC_Compliance/resources/schemas/wnprc_compliance.xml b/WNPRC_Compliance/resources/schemas/wnprc_compliance.xml
index 1ba2b3d2d..80be1b01e 100644
--- a/WNPRC_Compliance/resources/schemas/wnprc_compliance.xml
+++ b/WNPRC_Compliance/resources/schemas/wnprc_compliance.xml
@@ -106,6 +106,8 @@
+
+
diff --git a/WNPRC_Compliance/src/org/labkey/wnprc_compliance/view/unidentifiedCards.jsp b/WNPRC_Compliance/src/org/labkey/wnprc_compliance/view/unidentifiedCards.jsp
index b89e620e9..c6b020adf 100644
--- a/WNPRC_Compliance/src/org/labkey/wnprc_compliance/view/unidentifiedCards.jsp
+++ b/WNPRC_Compliance/src/org/labkey/wnprc_compliance/view/unidentifiedCards.jsp
@@ -217,7 +217,7 @@
WebUtils.VM.submitMarkExempt = function() {
$exemptDialog.modal('hide');
var cardData = ko.mapping.toJS(WebUtils.VM.form);
- WebUtils.API.postJSON("<%=q(urlFor(MarkCardExemptAPI.class))%>", {
+ WebUtils.API.postJSON(<%=q(urlFor(MarkCardExemptAPI.class))%>, {
cardId: cardData.selectedCard[0],
reason: cardData.notes
}).then(function(d) {
@@ -236,7 +236,7 @@
//TODO validate here...
//TODO not sure how this $parent selectedPerson really works here?
- WebUtils.API.postJSON("<%=q(urlFor(WNPRC_ComplianceController.LinkCardAPI.class))%>", {
+ WebUtils.API.postJSON(<%=q(urlFor(WNPRC_ComplianceController.LinkCardAPI.class))%>, {
cardId: cardData.selectedCard[0],
personId: personData.selectedPerson
}).then(function(d) {
@@ -285,7 +285,7 @@
} else {
// knockout wasn't playing nice here, using jQuery to force button to disabled
$(document).on('click', '#radio-person', function () {
- $('#link-card-button').removeProp('disabled');
+ $('#link-card-button').prop('disabled', false);
});
}
WebUtils.VM.listPersons.userMatches((PERSONS in results) ? results[PERSONS] : []);
diff --git a/WNPRC_EHR/resources/credits/jars.txt b/WNPRC_EHR/resources/credits/jars.txt
index 061fb4c99..f64477d89 100644
--- a/WNPRC_EHR/resources/credits/jars.txt
+++ b/WNPRC_EHR/resources/credits/jars.txt
@@ -1,6 +1,14 @@
{table}
-Filename|Component|Version|Source|License|LabKey Dev|Purpose
+Filename|Component|Version|Source|License|WNPRC Dev|Purpose
joda-time-2.8.1.jar|Joda-Time|2.8.1|{link:From GitHub|https://github.com/JodaOrg/joda-time}|{link:Apache Software License 2.0|http://www.apache.org/licenses/LICENSE-2.0}|jrichardson|Tools for dealing with dates/times in Java
-jsoup-1.10.3.jar|jsoup: Java HTML Parser|1.10.3|{link:From GitHub|https://github.com/jhy/jsoup}|{link:MIT License|https://opensource.org/licenses/MIT}|jricharson|Tools for parsing and manipulating HTML and CSS using the DOM
+jsoup-1.13.1.jar|jsoup: Java HTML Parser|1.10.3|{link:From GitHub|https://github.com/jhy/jsoup}|{link:MIT License|https://opensource.org/licenses/MIT}|jricharson|Tools for parsing and manipulating HTML and CSS using the DOM
reflections-0.9.10.jar|Reflections|0.9.10|{link:From GitHub|https://github.com/ronmamo/reflections}|{link:WTFPL|http://www.wtfpl.net/about/}|cstevens|Runtime analysis of Java classes and packages
-{table}
+google-api-client-1.23.0.jar|Google API Client for Java|1.30.5|{link:GitHub|https://github.com/googleapis/google-api-java-client}|{link:Apache License 2.0|https://github.com/googleapis/google-api-java-client/blob/master/LICENSE}|ggottfredsen|Library to interact with Google APIs
+google-api-services-calendar-v3-rev255-1.23.0.jar|Google Calendar API Client Library for Java|v3-rev20210708-1.32.1|{link:GitHub|https://github.com/googleapis/google-api-java-client-services/tree/master/clients/google-api-services-calendar/v3}|{link:Apache License 2.0|http://www.apache.org/licenses/LICENSE-2.0}|ggottfredsen|Library for interacting with Google Calendars in Java
+google-http-client-gson-1.23.0.jar|Google HTTP Client Library for Java|1.39.2-sp.1|{link:GitHub|https://github.com/googleapis/google-http-java-client/tree/master/google-http-client-gson}|{link:Apache License 2.0|https://github.com/googleapis/google-http-java-client/blob/master/LICENSE}|ggottfredsen|A flexible, efficient, and powerful Java library for accessing any resource on the web via HTTP
+google-auth-library-oauth2-http-0.19.0.jar|Google Auth Library|1.0.0|{link:GitHub|https://github.com/googleapis/google-auth-library-java/tree/master/oauth2_http}|{link:BSD 3-Clause "New" or "Revised" License|https://github.com/googleapis/google-auth-library-java/blob/master/LICENSE}|ggottfredsen|Contains a wide variety of credentials as well as utility methods to create them and to get Application Default Credentials
+commons-text-1.9.jar|Apache Commons Text|1.9|{link:GitHub|https://github.com/apache/commons-text}|{link:Apache License 2.0|https://github.com/apache/commons-text/blob/master/LICENSE.txt}|ggottfredsen|A library focused on algorithms working on strings
+msal4j-1.11.0.jar|Microsoft Authentication Library (MSAL) for Java|1.11.0|{link:GitHub|https://github.com/AzureAD/microsoft-authentication-library-for-java}|{link:MIT License|https://github.com/AzureAD/microsoft-authentication-library-for-java/blob/dev/LICENSE}|ggottfredsen|Allows to sign in users or apps with Microsoft identities (Azure AD, Microsoft accounts and Azure AD B2C accounts) and obtain tokens to call Microsoft APIs such as Microsoft Graph
+microsoft-graph-2.10.0.jar|Microsoft Graph Java SDK|2.10.0|{link:GitHub|https://github.com/microsoftgraph/msgraph-sdk-java}|{link:MIT License|https://github.com/microsoftgraph/msgraph-sdk-java/blob/dev/LICENSE}|ggottfredsen|Allows for interacting with Microsoft Graph (Calendars/User Accounts/Email/etc.)
+slf4j-nop-1.8.0-beta4.jar|Simple Logging Facade for Java|1.8.0-beta4|{link:GitHub|https://github.com/qos-ch/slf4j/tree/master/slf4j-nop}|{link:MIT License|https://github.com/qos-ch/slf4j/blob/master/LICENSE.txt}|ggottfredsen|Abstraction for various logging frameworks allowing for plugging in a desired framework at deployment time
+{table}
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/Biopsy/.qview.xml b/WNPRC_EHR/resources/queries/study/Biopsy/.qview.xml
index db3021f06..dc6386822 100644
--- a/WNPRC_EHR/resources/queries/study/Biopsy/.qview.xml
+++ b/WNPRC_EHR/resources/queries/study/Biopsy/.qview.xml
@@ -6,6 +6,7 @@
+
diff --git a/WNPRC_EHR/resources/queries/study/Demographics.query.xml b/WNPRC_EHR/resources/queries/study/Demographics.query.xml
index 50138b230..64bd32968 100644
--- a/WNPRC_EHR/resources/queries/study/Demographics.query.xml
+++ b/WNPRC_EHR/resources/queries/study/Demographics.query.xml
@@ -81,6 +81,12 @@
/ehr/participantView.view?participantId=${dam}
+
+ true
+
+
+ true
+ Sire
@@ -92,6 +98,9 @@
+
+ true
+ yyyy-MM-dd
@@ -102,6 +111,9 @@
query.Id~eq=${Id}
+
+ true
+ yyyy-MM-dd
@@ -214,6 +226,9 @@
+
+ true
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/WaterOrders/activeWaterOrders.qview.xml b/WNPRC_EHR/resources/queries/study/WaterOrders/activeWaterOrders.qview.xml
new file mode 100644
index 000000000..cefda070c
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/WaterOrders/activeWaterOrders.qview.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/WaterRecentWeight.sql b/WNPRC_EHR/resources/queries/study/WaterRecentWeight.sql
new file mode 100644
index 000000000..0cfd964dd
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/WaterRecentWeight.sql
@@ -0,0 +1,27 @@
+SELECT
+voGi.id,
+CAST (voGi.date AS DATE) AS Date,
+voGi.volume,
+voGi.RecentWeight,
+voGi.InnerWeight,
+voGi.objectid
+--voGi.DayDiff
+
+FROM (
+
+SELECT
+ wa.id AS id,
+ wa.date AS date,
+ wa.volume,
+ (SELECT we.weight
+ FROM study.weight we
+ --INNER JOIN study.weight wein
+ --ON we.id = wein.id
+ WHERE we.id = wa.id AND we.date = (SELECT MAX(wen.date) from study.weight wen WHERE wen.id=wa.id AND timestampdiff('SQL_TSI_DAY',wa.date,wen.date)<=0))AS InnerWeight,
+ (SELECT MAX(wen.date) from study.weight wen WHERE wen.id=wa.id AND timestampdiff('SQL_TSI_DAY',wa.date,wen.date)<=0) AS RecentWeight,
+ wa.objectid
+ --timestampdiff('SQL_TSI_DAY',wa.date ,wa.RecentWeight) AS DayDiff
+
+ FROM study.waterGiven wa
+) voGi
+--GROUP BY voGi.id, voGi.date,voGi.RecentWeight,voGi.InnerWeight
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/WaterScheduleWithWeight.sql b/WNPRC_EHR/resources/queries/study/WaterScheduleWithWeight.sql
new file mode 100644
index 000000000..f90306875
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/WaterScheduleWithWeight.sql
@@ -0,0 +1,41 @@
+SELECT
+ lsid AS lsid,
+ objectid AS objectIdCoalesced,
+ taskid AS taskid,
+ project AS projectCoalesced,
+ animalId AS animalId,
+ room || '-' || cage AS location,
+ date AS date,
+ dateOrdered AS dateOrdered,
+ startDateCoalesced AS startDateCoalesced,
+ volume AS volume,
+ provideFruit AS provideFruit,
+ provideFruitTitle AS provideFruitTitle,
+ dataSource AS dataSource,
+ assignedTo AS assignedToCoalesced,
+ assignedToTitle AS assignedToTitleCoalesced,
+ frequency AS frequencyCoalesced,
+ frequencyMeaning AS frequencyMeaningCoalesced,
+ timeofday AS timeofday,
+ displaytimeofday AS displaytimeofday,
+ qcstate AS qcstate,
+
+ --(SELECT max(wg.qcstate) as label FROM study.waterGiven wg WHERE WCO.objectid = wg.treatmentid AND WCO.dateOrdered = wg.dateordered ) AS waterStatus,
+ -- (SELECT timestampdiff(SQL_TSI_HOUR,WCO.date,wg.dateordered ) as diff FROM study.waterGiven wg WHERE WCO.objectid = wg.treatmentid ) AS difference,
+
+ (SELECT wg.weight AS weightAtDate
+ FROM study.weight wg
+ WHERE wg.id = WCO.animalId AND CAST(substring(CAST(wg.date AS VARCHAR) , 1, 10) AS DATE) <= WCO.date
+ ORDER BY wg.date DESC
+ LIMIT 1
+ ) AS weightAtDate,
+
+ (SELECT wg.date AS weightDate
+ FROM study.weight wg
+ WHERE wg.id = WCO.animalId AND CAST(substring(CAST(wg.date AS VARCHAR) , 1, 10) AS DATE) <= WCO.date
+ ORDER BY wg.date DESC
+ LIMIT 1
+ ) AS weightDate
+
+FROM study.waterScheduleCoalesced WCO
+--WHERE WCO.dateRangeStartDate >= curdate()
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/biopsy.query.xml b/WNPRC_EHR/resources/queries/study/biopsy.query.xml
index bf1262b80..9e28ac25f 100644
--- a/WNPRC_EHR/resources/queries/study/biopsy.query.xml
+++ b/WNPRC_EHR/resources/queries/study/biopsy.query.xml
@@ -15,6 +15,9 @@
NHPBMD
+
+ Billing Complete
+ Final Summary Comments
diff --git a/WNPRC_EHR/resources/queries/study/chairing.js b/WNPRC_EHR/resources/queries/study/chairing.js
new file mode 100644
index 000000000..77601acae
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/chairing.js
@@ -0,0 +1,90 @@
+require("ehr/triggers").initScript(this);
+var WNPRC = require("wnprc_ehr/WNPRC").WNPRC;
+require ("labkey");
+
+function onInit(event, helper){
+ helper.decodeExtraContextProperty('clientEncounterDate');
+
+ helper.registerRowProcessor(function(helper,row) {
+ if (!row)
+ return;
+ if(!row.Id || !row.date){
+ return;
+ }
+ var clientEncounterDate = helper.getProperty('clientEncounterDate');
+ clientEncounterDate = clientEncounterDate || {};
+ clientEncounterDate[row.Id] = clientEncounterDate [row.Id] || [];
+
+ if (row.objectid) {
+ LABKEY.ExtAdapter.each(clientEncounterDate[row.Id], function (r) {
+ if (r.objectid == row.objectid) {
+ if (r.date != row.date) {
+ r.date = row.date;
+ }
+ else {
+ return false;
+ }
+ }
+ }, this)
+ }
+ helper.setProperty('clientEncounterDate', clientEncounterDate);
+ });
+}
+function onUpsert(helper, scriptErrors, row, oldRow){
+
+ if (row.chairingStartTime){
+ var map = helper.getProperty('clientEncounterDate');
+ var clientEncounterDate = [];
+ if (map && map[row.Id]){
+ //console.log(map[row.Id]);
+ clientEncounterDate = map[row.Id];
+
+ }
+ let errorMessage = WNPRC.Utils.getJavaHelper().checkEncounterTime(row.Id,row.chairingStartTime,clientEncounterDate, 'chairing');
+ if (errorMessage != null){
+ EHR.Server.Utils.addError(scriptErrors,'chairingStartTime',errorMessage,'ERROR');
+ }
+
+ }
+
+ if (row.chairingEndTime){
+ var map = helper.getProperty('clientEncounterDate');
+ var clientEncounterDate = [];
+ if (map && map[row.Id]){
+ //console.log(map[row.Id]);
+ clientEncounterDate = map[row.Id];
+
+ }
+ let errorMessage = WNPRC.Utils.getJavaHelper().checkEncounterTime(row.Id,row.chairingEndTime,clientEncounterDate, 'chairing');
+ if (errorMessage != null){
+ EHR.Server.Utils.addError(scriptErrors,'chairingEndTime',errorMessage,'ERROR');
+ }
+
+ }
+
+ var startChairing = new Date (row.chairingStartTime.toGMTString());
+ var endChairing = new Date (row.chairingEndTime.toGMTString());
+
+
+ var _MS_PER_HOUR = 1000 * 60 * 60;
+
+ var timeDifference = parseInt(Math.ceil((endChairing - startChairing)/_MS_PER_HOUR));
+
+ if (timeDifference >12){
+
+ EHR.Server.Utils.addError(scriptErrors, 'chairingEndTime', 'An animal cannot be chaired for longer than 12 hours', 'ERROR');
+
+ }
+ if (timeDifference == 0){
+ EHR.Server.Utils.addError(scriptErrors, 'chairingEndTime', 'Chairing End time cannot be the same as Start time', 'ERROR');
+ }
+
+ //console.log ('chairing start time: '+ startChairing);
+ //console.log ('chairing end time: '+ endChairing);
+
+ if (endChairing < startChairing){
+ EHR.Server.Utils.addError(scriptErrors,'chairingEndTime', 'End time cannot be before the Start time', 'ERROR');
+ }
+
+
+}
diff --git a/WNPRC_EHR/resources/queries/study/chairing.query.xml b/WNPRC_EHR/resources/queries/study/chairing.query.xml
new file mode 100644
index 000000000..db1b6ff4b
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/chairing.query.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+ caseno
+
+
+
+ Chairing Start Time
+ Chairing Start Time
+ yyyy-MM-dd HH:mm
+
+
+
+ Chairing End Time
+ Chairing End Time
+ yyyy-MM-dd HH:mm
+
+
+
+ Chairing Location
+ Chairing Location
+
+ ehr_lookups
+ water_location
+ value
+
+
+
+
+ chairing
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/demographicsMostRecentWaterCondition.query.xml b/WNPRC_EHR/resources/queries/study/demographicsMostRecentWaterCondition.query.xml
new file mode 100644
index 000000000..871d67700
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/demographicsMostRecentWaterCondition.query.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
diff --git a/WNPRC_EHR/resources/queries/study/demographicsMostRecentWaterCondition.sql b/WNPRC_EHR/resources/queries/study/demographicsMostRecentWaterCondition.sql
new file mode 100644
index 000000000..ccc80310d
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/demographicsMostRecentWaterCondition.sql
@@ -0,0 +1,24 @@
+SELECT
+
+wsa.id,
+wsa.MostRecentWaterConditionDate,
+(
+ SELECT wsainner.mlsperKg
+ FROM study.waterScheduledAnimals wsainner
+ WHERE wsa.id = wsainner.id AND wsa.MostRecentWaterConditionDate = wsainner.date
+
+) AS mlsperKg,
+(
+ SELECT wsainner.condition
+ FROM study.waterScheduledAnimals wsainner
+ WHERE wsa.id = wsainner.id AND wsa.MostRecentWaterConditionDate = wsainner.date
+
+) AS MostRecentWaterCondition
+FROM(
+ SELECT
+ wsaouter.id as id,
+ max(wsaouter.date) AS MostRecentWaterConditionDate
+ FROM study.waterScheduledAnimals wsaouter
+ WHERE wsaouter.qcstate.publicdata = true AND wsaouter.condition IS NOT NULL
+ GROUP BY wsaouter.id
+ ) wsa
diff --git a/WNPRC_EHR/resources/queries/study/drug.js b/WNPRC_EHR/resources/queries/study/drug.js
new file mode 100644
index 000000000..58da39225
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/drug.js
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010-2014 LabKey Corporation
+ *
+ * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+require("ehr/triggers").initScript(this);
+var WNPRC = require("wnprc_ehr/WNPRC").WNPRC;
+
+function onInit(event,helper){
+ helper.decodeExtraContextProperty('clientEncounterDate');
+
+ helper.registerRowProcessor(function(helper,row) {
+ //TODO: pull this out and put into generic 'utils' function for reuse in other trigger scripts
+ if (!row)
+ return;
+ if(!row.Id || !row.date){
+ return;
+ }
+ var clientEncounterDate = helper.getProperty('clientEncounterDate');
+ clientEncounterDate = clientEncounterDate || {};
+ clientEncounterDate[row.Id] = clientEncounterDate [row.Id] || [];
+
+ if (row.objectid) {
+ LABKEY.ExtAdapter.each(clientEncounterDate[row.Id], function (r) {
+ if (r.objectid == row.objectid) {
+ if (r.date != row.date) {
+ r.date = row.date;
+ }
+ else {
+ return false;
+ }
+ }
+ }, this)
+ }
+ helper.setProperty('clientEncounterDate', clientEncounterDate);
+ });
+
+}
+function onUpsert(helper, scriptErrors, row, oldRow){
+ if (row.date){
+ var map = helper.getProperty('clientEncounterDate');
+ var clientEncounterDate = [];
+ if (map && map[row.Id]){
+ clientEncounterDate = map[row.Id];
+
+ }
+
+ if(clientEncounterDate.length > 0){
+ let errorMessage = WNPRC.Utils.getJavaHelper().checkEncounterTime(row.Id, row.date, clientEncounterDate, 'drug');
+ if (errorMessage != null) {
+ EHR.Server.Utils.addError(scriptErrors, 'date', errorMessage, 'ERROR');
+ }
+ }
+
+ }
+ if (helper.isETL())
+ return;
+
+// if(!row.amount && !row.volume){
+// EHR.Server.Utils.addError(scriptErrors, 'amount', 'Must supply either amount or volume', 'INFO');
+// EHR.Server.Utils.addError(scriptErrors, 'volume', 'Must supply either amount or volume', 'INFO');
+// }
+
+ if (row.qualifier && row.qualifier.match(/\//)){
+ EHR.Server.Utils.addError(scriptErrors, 'qualifier', 'This field contains a /. This likely means you need to pick one of the options', 'INFO');
+ }
+
+ //we need to store something in the date field during the draft stage, so i use header date
+ //we swap begindate in here instead
+ //any form that is an encounter should show begindate, not date
+ //other forms will not show begindate, so this shouldnt matter here
+ if (row.begindate)
+ row.date = row.begindate;
+
+ }
diff --git a/WNPRC_EHR/resources/queries/study/drug.query.xml b/WNPRC_EHR/resources/queries/study/drug.query.xml
new file mode 100644
index 000000000..1367448de
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/drug.query.xml
@@ -0,0 +1,183 @@
+
+
+
+
+ /ehr/drugDetails.view?lsid=${lsid}
+
+
+
+
+
+
+
+ Begin Date
+
+
+ Header Date
+ DateTime
+
+
+ End Time
+ false
+
+
+
+ ehr
+ project
+ project
+
+
+
+ Charge Unit
+
+ ehr_lookups
+ medicationChargeType
+ value
+
+
+
+
+ Code
+
+ ehr_lookups
+ snomed
+ code
+
+
+
+ Qualifier
+
+
+ Reason
+
+ ehr_lookups
+ drugReason
+ value
+
+
+
+ Route
+
+ ehr_lookups
+ routes
+ route
+
+
+
+
+ Dosage
+
+
+ Dosage Units
+
+ ehr_lookups
+ dosage_units
+ unit
+
+
+
+
+ Volume
+
+
+ Vol Units
+
+ ehr_lookups
+ volume_units
+ unit
+
+
+
+
+ Amount
+
+
+ Amount Units
+
+ ehr_lookups
+ amount_units
+ unit
+
+
+
+
+ Drug Conc
+
+
+ Conc Units
+
+ ehr_lookups
+ conc_units
+ unit
+
+
+
+
+ Restraint
+
+ ehr_lookups
+ restraint_type
+ type
+
+
+
+ Time Restrained
+
+ ehr_lookups
+ restraint_duration
+ value
+
+
+
+ Outcome
+
+ ehr_lookups
+ drugOutcome
+ value
+
+
+ Normal
+
+
+ Lot
+
+
+ Remark
+
+
+ Category
+
+ ehr_lookups
+ drug_categories
+ value
+
+
+
+
+ Begin Date
+
+
+ Treatment Id
+ true
+
+
+ Time Ordered
+ For drugs that were ordered using the Treatment Orders table, this stores the original time this administration was scheduled to be administered.
+ true
+
+
+
+
+
+ true
+
+
+ ehr_lookups
+ implant_area
+ value
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/drug/.qview.xml b/WNPRC_EHR/resources/queries/study/drug/.qview.xml
index 141fa24dc..725fc6733 100644
--- a/WNPRC_EHR/resources/queries/study/drug/.qview.xml
+++ b/WNPRC_EHR/resources/queries/study/drug/.qview.xml
@@ -10,6 +10,7 @@
+
@@ -23,6 +24,7 @@
+
diff --git a/WNPRC_EHR/resources/queries/study/restraints.js b/WNPRC_EHR/resources/queries/study/restraints.js
index ff0435f5e..d5cbf77a1 100644
--- a/WNPRC_EHR/resources/queries/study/restraints.js
+++ b/WNPRC_EHR/resources/queries/study/restraints.js
@@ -16,6 +16,11 @@ function onUpdate(helper, scriptErrors, row, oldRow) {
}
function onUpsert(helper, scriptErrors, row, oldRow) {
+ if (row.restraintType == 'Other'){
+ if(!row.remarks){
+ EHR.Server.Utils.addError(scriptErrors, 'remarks', 'Remarks are required when Other is selected from restraint type')
+ }
+ }
}
function setDescription(row, helper){
diff --git a/WNPRC_EHR/resources/queries/study/restraints.query.xml b/WNPRC_EHR/resources/queries/study/restraints.query.xml
index a144c4a55..f4d058631 100644
--- a/WNPRC_EHR/resources/queries/study/restraints.query.xml
+++ b/WNPRC_EHR/resources/queries/study/restraints.query.xml
@@ -13,6 +13,7 @@
Restraint Type
+ Restraint Typeehr_lookupsrestraint_type
@@ -20,6 +21,7 @@
+ restraints
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterAmount.js b/WNPRC_EHR/resources/queries/study/waterAmount.js
new file mode 100644
index 000000000..2da71cafa
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterAmount.js
@@ -0,0 +1,108 @@
+require("ehr/triggers").initScript(this);
+var WNPRC = require("wnprc_ehr/WNPRC").WNPRC;
+
+function onInit(event, helper){
+ helper.setScriptOptions({
+ allowFutureDates: true
+ });
+ helper.decodeExtraContextProperty('waterInForm');
+ helper.decodeExtraContextProperty('clientEncounterDate');
+
+ helper.registerRowProcessor(function (helper, row){
+ if (!row)
+ return;
+ if(!row.Id || !row.volume){
+ return;
+ }
+
+ var waterInForm = helper.getProperty('waterInForm');
+ waterInForm = waterInForm || {};
+ waterInForm[row.Id] = waterInForm[row.Id] || [];
+
+ var clientEncounterDate = helper.getProperty('clientEncounterDate');
+ clientEncounterDate = clientEncounterDate || {};
+ clientEncounterDate[row.Id] = clientEncounterDate [row.Id] || [];
+
+ if (row.objectid){
+ LABKEY.ExtAdapter.each(waterInForm[row.Id], function(r){
+ if (r.objectid == row.objectid){
+ if(r.volume != row.volume){
+ r.volume = row.volume;
+ }
+ else{
+ return false;
+ }
+ }
+ }, this)
+
+ LABKEY.ExtAdapter.each(clientEncounterDate[row.Id], function(r){
+ if (r.objectid == row.objectid){
+ if(r.date != row.date){
+ r.date = row.date;
+ }
+ else{
+ return false;
+ }
+ }
+ }, this)
+ }
+ helper.setProperty('waterInForm',waterInForm);
+ helper.setProperty('clientEncounterDate',clientEncounterDate);
+ });
+
+}
+
+function onUpsert(helper, scriptErrors, row, oldRow) {
+
+ if (row.date){
+ var map = helper.getProperty('clientEncounterDate');
+
+ var clientEncounterDate = [];
+ if (map && map[row.Id]){
+ clientEncounterDate = map[row.Id];
+
+ }
+ let errorMessage = WNPRC.Utils.getJavaHelper().checkEncounterTime(row.Id,row.date,clientEncounterDate, 'waterAmount');
+ if (errorMessage != null){
+ EHR.Server.Utils.addError(scriptErrors,'date',errorMessage,'ERROR');
+ }
+
+ }
+
+ if (row.recordSource=="LabWaterForm"){
+ var fixdate = new Date(row.date);
+ fixdate.setHours(14);
+ fixdate.setMinutes(1);
+ row.date = fixdate;
+ if (!row.skipWaterRegulationCheck){
+ row.qcstate = EHR.Server.Security.getQCStateByLabel('Scheduled').rowid;
+ row.QCStateLabel = EHR.Server.Security.getQCStateByLabel('Scheduled').Label;
+ }
+
+ if (row.assignedTo == "animalcare" && row.volume && !row.skipWaterRegulationCheck){
+ let errorMessage = WNPRC.Utils.getJavaHelper().checkUploadTime(row.id,row.date,row.recordSource,row.assignedTo, 'waterAmount');
+ if (errorMessage != null){
+ EHR.Server.Utils.addError(scriptErrors,'assignedTo',errorMessage,'INFO');
+ }
+ }
+ if (row.volume && row.waterSource == "regulated" && !row.skipWaterRegulationCheck){
+ var map = helper.getProperty('waterInForm');
+ var waterInForm = [];
+ if (map && map[row.Id]){
+ waterInForm = map[row.Id];
+ }
+
+ let jsonArray = WNPRC.Utils.getJavaHelper().checkWaterSchedule(row.id,row.date,row.objectid,row.volume,waterInForm);
+ if (jsonArray != null){
+ for (var i = 0; i < jsonArray.length; i++ ){
+ let errorObject = JSON.parse(jsonArray[i]);
+ EHR.Server.Utils.addError(scriptErrors,errorObject.field, errorObject.message,errorObject.severity);
+
+ }
+ }
+
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterAmount.query.xml b/WNPRC_EHR/resources/queries/study/waterAmount.query.xml
new file mode 100644
index 000000000..adf64a79b
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterAmount.query.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Date Ordered
+ yyyy-MM-dd HH:mm
+
+
+
+
+
+ Volume (mL)
+
+
+ Provide Fruit
+
+ ehr_lookups
+ husbandry_fruit
+ Value
+
+
+
+ Assigned To
+
+ ehr_lookups
+ husbandry_assigned
+ Value
+
+
+
+ Frequency
+
+ wnprc
+ husbandry_frequency
+ rowid
+
+
+
+ Water Source
+
+ ehr_lookups
+ water_source
+ value
+ title
+
+
+
+ Record Source
+
+
+
+
+
+
+
+
+
diff --git a/WNPRC_EHR/resources/queries/study/waterGiven.js b/WNPRC_EHR/resources/queries/study/waterGiven.js
new file mode 100644
index 000000000..15fe88087
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterGiven.js
@@ -0,0 +1,267 @@
+require("ehr/triggers").initScript(this);
+var WNPRC = require("wnprc_ehr/WNPRC").WNPRC;
+
+//EHR.Server.Utils = require("ehr/utils").EHR.Server.Utils;
+
+function onInit(event, helper){
+ //This extracontext is used in the Water Orders form
+ helper.decodeExtraContextProperty('waterInTransaction');
+ //This extracontext is used in the Lab Water form
+ helper.decodeExtraContextProperty('waterInForm');
+
+ helper.setScriptOptions({
+ allowDeadIds: true,
+ allowAnyId: true,
+ skipIdFormatCheck: true,
+ allowFutureDates: true,
+ isSkipAssignmentCheck: true
+ });
+
+ helper.registerRowProcessor(function(helper, row){
+ if (!row)
+ return;
+
+ if (!row.Id || !row.date){
+ return;
+ }
+ if (row.taskid){
+
+ }
+
+ var waterInTransaction = helper.getProperty('waterInTransaction');
+ waterInTransaction = waterInTransaction || [];
+ waterInTransaction[row.Id] = waterInTransaction[row.Id] || [];
+
+ var waterInForm = helper.getProperty('waterInForm');
+ waterInForm = waterInForm || {};
+ waterInForm[row.Id] = waterInForm[row.Id] || [];
+
+ if (row.objectid)
+ {
+ var shouldAdd = true;
+ LABKEY.ExtAdapter.each(waterInTransaction[row.Id], function (r){
+ if (r.objectid == row.objectid){
+ if (r.volume != row.volume){
+ r.volume = row.volume;
+ }
+ else {
+ shouldAdd = false;
+ return;
+ }
+ }
+
+ }, this);
+
+ LABKEY.ExtAdapter.each(waterInForm[row.Id], function(r){
+ if (r.objectid == row.objectid){
+ if(r.volume != row.volume){
+ r.volume = row.volume;
+ }
+ else{
+ return false;
+ }
+ }
+ }, this)
+ }
+
+ if (shouldAdd){
+ waterInTransaction[row.Id].push({
+ objectid: row.objectid,
+ date: row.date,
+ datasource: row.datasource,
+ qcstate: row.qcstate,
+ assignedto: row.assignedto,
+ parentid: row.parentid,
+ volume: row.volume,
+ lsid: row.lsid
+
+ });
+ }
+
+ helper.setProperty('waterInForm',waterInForm);
+ helper.setProperty('waterInTransaction', waterInTransaction);
+ });
+}
+
+function onUpsert(helper, scriptErrors, row, oldRow) {
+ /*if (row.volume == null){
+ EHR.Server.Utils.addError(scriptErrors, 'volume', 'This field is required', 'WARN');
+ console.log ("value of QCState "+ row.QCState)
+ }*/
+
+ if (row.QCStateLabel == 'Scheduled'){
+ console.log ("value of date given "+ row.date);
+ EHR.Server.Validation.verifyDate(row, scriptErrors, helper);
+
+ /*if(row.QCStateLabel == 'Scheduled'){
+ //TODO: add special condition for water given
+ currentTimeRounded.setHours(13,30,0,0);
+ console.log ('RowTime at 1:30 PM '+currentTimeRounded);
+ console.log ('Rowtime '+ date);
+ if (date>currentTimeRounded){
+ EHR.Server.Utils.addError(errors, 'date', 'Cannot schedule water after 13:30 PM', 'ERROR');
+ }
+
+ }*/
+ }
+
+ if (row.Id && row.date)
+ {
+ // volume is handled differently for requestsvs actual draws
+ var errorQC = 'ERROR';
+ //if (EHR.Server.Security.getQCStateByLabel(row.QCStateLabel)['isRequest'] && !row.taskid)
+ // errorQC = 'ERROR';
+ //else
+ // errorQC = 'INFO';
+
+ var map = helper.getProperty('waterInTransaction');
+ var waters = [];
+ if (map && map[row.Id])
+ {
+ waters = map[row.Id];
+ /*for (var i=0;i
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yyyy-MM-dd HH:mm
+
+
+ yyyy-MM-dd HH:mm
+
+
+ Performed By
+
+
+
+ Volume (mL)
+
+
+
+ Provide Fruit
+
+ ehr_lookups
+ husbandry_fruit
+ value
+
+
+
+
+
+
+ Water Source
+
+ ehr_lookups
+ water_source
+ value
+ title
+
+
+
+ Water Location
+ 250
+
+ ehr_lookups
+ water_location
+ value
+
+
+
+ Route
+
+ ehr_lookups
+ routes
+ route
+
+
+
+
+ Assigned To
+
+ ehr_lookups
+ husbandry_assigned
+ value
+
+
+
+
+
+
+
+
+ Room
+
+
+
+ study
+ demographicsMostRecentWeight
+ MostRecentWeight
+
+
+
+ false
+
+
+
+
+
+
diff --git a/WNPRC_EHR/resources/queries/study/waterOrders.js b/WNPRC_EHR/resources/queries/study/waterOrders.js
new file mode 100644
index 000000000..c5d4ce7be
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterOrders.js
@@ -0,0 +1,128 @@
+require("ehr/triggers").initScript(this);
+var WNPRC = require("wnprc_ehr/WNPRC").WNPRC;
+
+function onInit(event, helper){
+ helper.setScriptOptions({
+ allowFutureDates: true
+ });
+}
+
+function onUpsert(helper, scriptErrors, row, oldRow){
+ console.log("print oldRow "+ oldRow);
+
+ if (row.Id){
+ EHR.Server.Utils.findDemographics({
+ participant: row.Id,
+ helper: helper,
+ scope: this,
+ callback: function(data){
+ if(data){
+ if(!row.project){
+ EHR.Server.Utils.addError(scriptErrors, 'project', 'Must enter a project for all center animals.', 'WARN');
+ }
+ }
+ }
+ });
+ var animalRestricted = {};
+ animalRestricted = WNPRC.Utils.getJavaHelper().checkIfAnimalInCondition(row.Id, row.date);
+ //console.log (animalRestricted);
+ if (!animalRestricted && !row.skipWaterRegulationCheck){
+ EHR.Server.Utils.addError(scriptErrors,'Id', 'Animal not assigned to water restriction protocol or is already in ' + row.waterSource + ' condition.', 'ERROR');
+ }
+
+
+
+ }
+
+ var today = new Date();
+ //console.log("Value of date " + row.date);
+ //console.log("Value of start date " + row.startdate);
+ today.setHours(0,0,0,0);
+
+ var rowDate = new Date(row.date);
+ rowDate.setHours(0,0,0,0);
+ EHR.Server.Utils.removeTimeFromDate(row,scriptErrors,"date");
+
+ //console.log("Value of date " + rowDate + " "+ rowDate.getTime());
+ //console.log("Value of start date " + row.startdate);
+ //console.log("Value of today "+ today+ " "+ today.getTime());
+
+
+ //TODO: allow updates of existing records.
+ if(!(rowDate.getTime() >= today.getTime()) && (oldRow.objectid != row.objectid)){
+ EHR.Server.Utils.addError(scriptErrors, 'date', 'Only Dates in the Future Allow', 'ERROR');
+ }
+
+ var endDate = new Date(row.enddate);
+ endDate.setHours(0,0,0,0);
+
+ //This does not get checked when the dataset if updated, only when using Ext4 form
+ if (rowDate.getTime() > endDate.getTime()){
+ EHR.Server.Utils.addError(scriptErrors,'endDate', 'EndDate cannot be before StartDate', 'ERROR');
+ }
+
+ if (!row.frequency && row.waterSource == 'regulated'){
+ EHR.Server.Utils.addError(scriptErrors, 'frequency', 'Frequency is required when entering regulated water orders.', 'ERROR');
+ }
+ if (!row.volume && row.waterSource == 'regulated'){
+ //console.log ("water vol "+ row.volume);
+ EHR.Server.Utils.addError(scriptErrors, 'volume', 'Volume is required when entering regulated water orders.', 'ERROR');
+ }
+
+ if (!row.assignedTo && row.waterSource == 'regulated'){
+ EHR.Server.Utils.addError(scriptErrors, 'assignedTo', 'Assigned To is required when entering regulated water orders.', 'ERROR');
+ }
+
+ if (!row.waterSource){
+ EHR.Server.Utils.addError(scriptErrors, 'waterSource', 'Water Source is required when entering new orders.', 'ERROR');
+ }
+
+ //console.log ("value of ObjectId "+oldRow.objectid + " Value of new objectId "+ row.objectid);
+ //console.log ('skipWaterRegulation '+ row.skipWaterRegulationCheck);
+ // if (oldRow && row.date && row.Id && row.frequency && (oldRow.objectid != row.objectid)) {
+ if (row.project && row.objectid && row.Id && row.date && row.frequency && row.assignedTo && row.waterSource != 'lixit' && !row.skipWaterRegulationCheck) {
+ console.log('value of row: frequency ' + row.frequency + ' value of waterSource ' + row.waterSource);
+ let jsonArray = WNPRC.Utils.getJavaHelper().checkWaterRegulation(row.id, row.date, row.enddate ? row.enddate : null, row.frequency, row.waterSource, row.objectid, row.project, this.extraContext);
+ if (jsonArray != null) {
+ for (var i = 0; i < jsonArray.length; i++) {
+ var errorObject = JSON.parse(jsonArray[i]);
+ EHR.Server.Utils.addError(scriptErrors, errorObject.field, errorObject.message, errorObject.severity);
+ }
+ }
+ row.date = rowDate;
+ }
+
+ //if (oldRow && oldRow.waterSource == 'regulated' && row.waterSource == 'lixit'){
+ //TODO: by pass water regulation to change water order to lixit and also chnage the water regulated animals data
+ if ( row.waterSource == 'lixit' && !row.skipWaterRegulationCheck && !oldRow){
+
+ let jsonArray = WNPRC.Utils.getJavaHelper().changeWaterScheduled(row.id,row.date,row.waterSource, row.project, row.objectid,this.extraContext);
+ let jsonExtraContext = this.extraContext.extraContextArray;
+
+ if (jsonArray != null){
+ for (var i=0; i < jsonArray.length; i++){
+ let errorObject = JSON.parse(jsonArray[i]);
+ EHR.Server.Utils.addError(scriptErrors,errorObject.field, errorObject.message, errorObject.severity);
+
+ }
+ console.log(" Printing Extra Context" + jsonExtraContext);
+ if (jsonExtraContext != null){
+ for (var i = 0; i < jsonExtraContext.length; i++){
+ let extraContextObject = jsonExtraContext[i];
+ let date = extraContextObject.date;
+ let dateOnly = new Date(date.getTime());
+ dateOnly = dateOnly.getFullYear()+ "-" +dateOnly.getMonth()+ "-" + dateOnly.getDate();
+ let infoMessage = "Water Order for "+ row.Id + " started on " + dateOnly + " with frequency of " + extraContextObject.frequency + " and volume of " + extraContextObject.volume + "ml will close.";
+ //console.log(infoMessage);
+ EHR.Server.Utils.addError(scriptErrors,"waterSource",infoMessage,"INFO")
+
+ }
+
+ }
+
+ }
+ }
+
+
+
+}
diff --git a/WNPRC_EHR/resources/queries/study/waterPivot.query.xml b/WNPRC_EHR/resources/queries/study/waterPivot.query.xml
new file mode 100644
index 000000000..9c808d2ff
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterPivot.query.xml
@@ -0,0 +1,33 @@
+
+
+
+
+ Water Grid
+
+
+
+
+
+
+
+
+ study
+ animal
+ Id
+
+
+
+ Goals For Day
+
+ /EHR/cageDetails.view?
+ room=${room}&
+ cage=${cage}&
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterPivot.sql b/WNPRC_EHR/resources/queries/study/waterPivot.sql
new file mode 100644
index 000000000..60094941c
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterPivot.sql
@@ -0,0 +1,25 @@
+SELECT
+--wa.id, wa.Date, wa.amountGivenInLab, wa.amountGivenInCage, wa.total, wa.weight
+wp.id,
+CAST (wp.date AS DATE) AS Date,
+
+--max(wa.amount) AS goal,
+CAST(COALESCE ((SELECT SUM (CAST (iwg.volume AS NUMERIC)) FROM study.waterGiven iwg WHERE iwg.id=wp.id AND (dayofyear(iwg.date)-dayofyear(wp.date)) =0 AND iwg.assignedto LIKE 'laboratory'),0) AS NUMERIC) AS volumeGivenInLab,
+CAST(COALESCE ((SELECT SUM (CAST (iwg.volume AS NUMERIC)) FROM study.waterGiven iwg WHERE iwg.id=wp.id AND (dayofyear(iwg.date)-dayofyear(wp.date)) =0 AND iwg.assignedto LIKE 'animalcare'),0) AS NUMERIC) AS volumeGivenInCage,
+
+CAST((SELECT SUM (CAST (iwg.volume AS NUMERIC)) FROM study.waterGiven iwg WHERE iwg.id=wp.id AND (dayofyear(iwg.date)-dayofyear(wp.date)) =0) AS NUMERIC) AS Total,
+CAST(((SELECT SUM (CAST (iwg.volume AS NUMERIC))
+ FROM study.waterGiven iwg
+ WHERE iwg.id=wp.id AND (dayofyear(iwg.date)-dayofyear(wp.date)) =0)-(20*(SELECT dm.id.MostRecentWeight.MostRecentWeight AS MostRecentWieght FROM study.demographics dm WHERE wp.id = dm.id))) AS NUMERIC) AS Weight
+--sum(wp.Weight) AS Weight
+
+FROM study.waterGiven wp
+
+--WHERE wp.Date > '2015-02-13' and wp.id='r02086'
+
+GROUP BY wp.id, wp.date
+--GROUP BY wa.id, wa.date, wa.volumeGivenInLab, wa.volumeGivenInCage, wa.total, wa.weight
+
+--PIVOT goal BY id
+PIVOT Weight,total,volumeGivenInLab, volumeGivenInCage BY id
+--PIVOT weight,total BY id
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterPrePivot.query.xml b/WNPRC_EHR/resources/queries/study/waterPrePivot.query.xml
new file mode 100644
index 000000000..e2ca1c8ab
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterPrePivot.query.xml
@@ -0,0 +1,72 @@
+
+
+
+
+ Water Grid
+
+
+
+
+
+
+
+
+ study
+ animal
+ Id
+
+
+
+ Goals For Day
+
+ /EHR/cageDetails.view?
+ room=${room}&
+ cage=${cage}&
+
+
+
+
+
+
+ core
+ QCState
+ rowId
+ Label
+
+
+
+
+
+
+
+
+ FF0000
+
+
+
+
+ ml Water Per Kg
+
+
+
+
+
+ E74C3C
+
+
+
+
+
+
+
+ Allowed MlsPerKg
+
+
+ Date of Allowed MlsPerKg
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterPrePivot.sql b/WNPRC_EHR/resources/queries/study/waterPrePivot.sql
new file mode 100644
index 000000000..6c8460d33
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterPrePivot.sql
@@ -0,0 +1,75 @@
+SELECT DISTINCT
+voGi.id as animalId,
+CAST (voGi.date AS DATE) AS date,
+--voGi.projectConcat AS projectConcat,
+voGi.performedConcat AS performedConcat,
+CAST (voGi.qcstateConcat AS INTEGER) AS qcstate,
+
+voGi.volumeGivenInLabSub,
+voGi.volumeGivenInCage,
+voGi.volumeGivenInImage,
+voGi.volumeGivenInProcedure,
+
+voGi.TotalWater AS TotalWater,
+voGi.TotalWater AS volume,
+voGi.RecentWeight,
+voGi.InnerWeight,
+
+
+TRUNCATE(ROUND(CAST(voGi.TotalWater /voGi.InnerWeight AS NUMERIC),2),2) AS mlsPerKg,
+voGi.InnerWeight*voGi.InnerMlsPerKg - voGi.TotalWater AS WaterRemaining,
+
+voGi.RecentMlsPerKg,
+voGi.InnerMlsPerKg,
+
+'waterGiven' AS dataSource
+
+FROM (
+
+ SELECT
+ wa.id AS id,
+ wa.date AS date,
+ --GROUP_CONCAT(DISTINCT wa.project, ';') AS projectConcat,
+ COALESCE((SELECT GROUP_CONCAT(iwg.performedby, ';') FROM study.waterGiven iwg WHERE iwg.id=wa.id AND (dayofyear(iwg.date)-dayofyear(wa.date)) = 0),' ') AS performedConcat,
+ COALESCE((SELECT DISTINCT( iwg.qcstate) FROM study.waterGiven iwg WHERE iwg.id=wa.id AND iwg.qcstate.label = 'Completed' AND (dayofyear(iwg.date)-dayofyear(wa.date)) = 0),'22') AS qcstateConcat,
+ COALESCE ((SELECT SUM(CAST(iwg.volume AS NUMERIC)) FROM study.waterGiven iwg WHERE iwg.id=wa.id AND (dayofyear(iwg.date)-dayofyear(wa.date)) = 0 AND iwg.location LIKE 'lab'),0) AS volumeGivenInLabSub,
+ COALESCE ((SELECT SUM(CAST(iwg.volume AS NUMERIC)) FROM study.waterGiven iwg WHERE iwg.id=wa.id AND (dayofyear(iwg.date)-dayofyear(wa.date)) = 0 AND iwg.location LIKE 'animalRoom'),0) AS volumeGivenInCage,
+ COALESCE ((SELECT SUM(CAST(iwg.volume AS NUMERIC)) FROM study.waterGiven iwg WHERE iwg.id=wa.id AND (dayofyear(iwg.date)-dayofyear(wa.date)) = 0 AND iwg.location LIKE 'imaging'),0) AS volumeGivenInImage,
+ COALESCE ((SELECT SUM(CAST(iwg.volume AS NUMERIC)) FROM study.waterGiven iwg WHERE iwg.id=wa.id AND (dayofyear(iwg.date)-dayofyear(wa.date)) = 0 AND iwg.location LIKE 'procedureRoom'),0) AS volumeGivenInProcedure,
+ COALESCE ((SELECT SUM (CAST (iwg.volume AS NUMERIC)) FROM study.waterGiven iwg WHERE iwg.id=wa.id AND (dayofyear(iwg.date)-dayofyear(wa.date)) =0),0) AS TotalWater,
+ (SELECT we.weight
+ FROM study.weight we
+ WHERE we.id = wa.id AND we.date = (
+ SELECT MAX(wen.date)
+ FROM study.weight wen
+ WHERE (wen.id=wa.id AND timestampdiff('SQL_TSI_DAY',wa.date,wen.date)>=0 AND wen.weight IS NOT NULL AND wen.date <= wa.date)
+ )
+ ) AS InnerWeight,
+ (SELECT MAX(wen.date)
+ FROM study.weight wen
+ WHERE (wen.id=wa.id AND timestampdiff('SQL_TSI_DAY',wa.date,wen.date)>=0 AND wen.weight IS NOT NULL AND wa.date >= wen.date)
+ ) AS RecentWeight,
+
+ --Showing latest mlsPerKg from Water Schedules Dataset
+ (SELECT wsa.mlsperKg
+ FROM study.waterScheduledAnimals wsa
+ WHERE wsa.id = wa.id AND wsa.date = (
+ SELECT MAX(wsaDate.date)
+ FROM study.waterScheduledAnimals wsaDate
+ WHERE (wsaDate.id=wa.id AND wsaDate.mlsperKg IS NOT NULL AND wsaDate.date <= wa.date)
+ )
+ ) AS InnerMlsPerKg,
+ (SELECT MAX(wsa.date)
+ FROM study.waterScheduledAnimals wsa
+ WHERE (wsa.id=wa.id AND wsa.mlsperKg IS NOT NULL AND wa.date >= wsa.date)
+ ) AS RecentMlsPerKg
+
+ FROM study.waterGiven wa
+ WHERE wa.qcstate.label = 'Completed'
+ GROUP BY wa.id, wa.date
+
+) voGi
+WHERE voGi.InnerWeight IS NOT NULL
+--GROUP BY voGi.id,voGi.date,voGi.projectConcat,voGi.performedConcat,voGi.qcstateConcat,voGi.volumeGivenInLabSub,voGi.volumeGivenInCage,voGi.volumeGivenInImage,voGi.volumeGivenInProcedure,voGi.TotalWater,voGi.RecentWeight,voGi.InnerWeight,voGi.RecentMlsPerKg,voGi.InnerMlsPerKg
+GROUP BY voGi.id,voGi.date,voGi.performedConcat,voGi.qcstateConcat,voGi.volumeGivenInLabSub,voGi.volumeGivenInCage,voGi.volumeGivenInImage,voGi.volumeGivenInProcedure,voGi.TotalWater,voGi.RecentWeight,voGi.InnerWeight,voGi.RecentMlsPerKg,voGi.InnerMlsPerKg
+--voGi.Weight
diff --git a/WNPRC_EHR/resources/queries/study/waterPrePivot/.qview.xml b/WNPRC_EHR/resources/queries/study/waterPrePivot/.qview.xml
new file mode 100644
index 000000000..932a4d486
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterPrePivot/.qview.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterRemaining.sql b/WNPRC_EHR/resources/queries/study/waterRemaining.sql
new file mode 100644
index 000000000..cd172b204
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterRemaining.sql
@@ -0,0 +1,5 @@
+SELECT
+*,
+wg.id.dataset.activehousing.room as CurrentRoom,
+wg.id.dataset.activehousing.cage as CurrentCage,
+FROM waterGiven wg
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterSchedule.query.xml b/WNPRC_EHR/resources/queries/study/waterSchedule.query.xml
new file mode 100644
index 000000000..f8446803f
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterSchedule.query.xml
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterSchedule.sql b/WNPRC_EHR/resources/queries/study/waterSchedule.sql
new file mode 100644
index 000000000..24cd58ff8
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterSchedule.sql
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010-2014 LabKey Corporation
+ *
+ * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+SELECT
+d.id AS animalId,
+d.calculated_status,
+s.*,
+s.objectid as treatmentid,
+--(SELECT max(d.qcstate) as label FROM study.drug d WHERE s.objectid = d.treatmentid AND s.date = d.timeordered) as treatmentStatus,
+COALESCE((SELECT max(wg.qcstate) as label FROM study.waterGiven wg WHERE wg.treatmentid LIKE '%' || s.objectid || '%' AND s.date = wg.dateordered AND wg.volume IS NOT NULL ),10) as waterStatus,
+--COALESCE((SELECT max(wg.qcstate) as label FROM study.waterGiven wg WHERE s.objectid IN (wg.treatmentid) AND s.date = wg.dateordered AND wg.volume IS NOT NULL ),10) as waterStatus,
+COALESCE((SELECT max(wg.treatmentid) as treatmentIds FROM study.waterGiven wg WHERE s.date = wg.dateordered AND wg.volume IS NOT NULL ),'objectId') as watertreatment
+
+
+FROM study.demographics d
+
+JOIN (
+ SELECT
+ s.*,
+ timestampadd('SQL_TSI_MINUTE', ((s.hours * 60) + s.minutes ), s.origDate) as date,
+ CASE
+ WHEN (hours >= 6 AND hours < 12) THEN 'AM'
+ WHEN (hours < 20 OR hours >= 12) THEN 'PM'
+ ELSE 'Other'
+ END as timeOfDay,
+
+ ((s.hours * 60) + s.minutes) as timeOffset
+
+ FROM (
+
+ SELECT
+
+ t1.objectid,
+ t1.taskid,
+ t1.lsid,
+ t1.dataset,
+ t1.id as wanimalid,
+
+ COALESCE ( ft.hourofday, ((hour(t1.date) * 100) + minute(t1.date))) as time,
+ (coalesce( (ft.hourofday), (hour(t1.date) * 100)) / 100) as hours,
+ CASE
+ WHEN ( ft.hourofday IS NOT NULL)
+ THEN (((ft.hourofday / 100.0) - floor(ft.hourofday / 100)) * 100)
+ ELSE minute(t1.date)
+ END as minutes,
+
+ dr.date as origDate,
+ t1.created AS created,
+ t1.id.curLocation.area as area,
+ t1.id.curLocation.room as room,
+ t1.id.curLocation.cage as cage,
+ dr.startDate AS dateRangeStartDate,
+ t1.date as startDate,
+ timestampdiff('SQL_TSI_DAY', cast(t1.dateOnly as timestamp), dr.dateOnly) + 1 as daysElapsed,
+ t1.enddate,
+ t1.enddateCoalescedFuture, --column use to display future dates when the endDate is null
+ t1.frequency AS frequency,
+ t1.frequency.meaning AS freqMeaning,
+ ft.timedescription AS displaytimeofday,
+ t1.provideFruit AS provideFruit,
+ t1.provideFruit.title AS provideFruitTitle,
+ t1.assignedTo,
+ t1.assignedTo.title AS assignedToTittle,
+ t1.waterSource,
+ t1.project,
+ t1.volume,
+ t1.qcstate
+
+ FROM ehr_lookups.dateRange dr
+
+ JOIN study.waterOrders t1
+ --NOTE: should the enddate consider date/time?
+ ON dr.dateOnly >= t1.dateOnly AND dr.dateOnly <= t1.enddateCoalescedFuture
+
+ LEFT JOIN ehr_lookups.treatment_frequency_times ft ON (ft.frequency = t1.frequency.meaning)
+
+ INNER JOIN
+ wnprc.husbandry_frequency hf
+ -- Frequencies that are not daily, we used the dayofweek tp populate schedule
+ -- If daily it shows every day.
+ ON (
+ ((hf.meaning = t1.frequency.meaning)
+ AND (t1.frequency.meaning LIKE 'Daily%')
+ )
+ OR
+ ((hf.meaning = t1.frequency.meaning)
+ AND (t1.frequency.meaning NOT LIKE 'Daily%')
+ AND (dayofweek(dr.date) = hf.dayofweek)
+ )
+ )
+
+
+ --NOTE: if we run this report on a future interval, we want to include those treatments
+ WHERE t1.date is not null --AND QCState = '1'
+
+ ) s
+
+) s ON (s.wanimalid = d.id)
+
+WHERE (d.lastDayatCenter Is Null OR d.lastDayAtCenter >= s.enddateCoalescedFuture)
+
+--Adding differet frequecies time
+
+
+--account for date/time in schedule
+--origDate has to have 00:00 a time otherwise it does not include the first day of the order
+and s.origDate >= s.startDate and s.origDate <= s.enddateCoalescedFuture
+
+--Filtering water regulated
+--AND (s.waterSource = 'regulated' OR s.startDate = s.origDate)
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced.query.xml b/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced.query.xml
new file mode 100644
index 000000000..897b9c54b
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced.query.xml
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced.sql b/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced.sql
new file mode 100644
index 000000000..0a743a2c2
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced.sql
@@ -0,0 +1,73 @@
+-- UNION ALL faster query
+-- water amount not matching time, need to add water amount according to the time set of the frequency
+-- the date will match as it does with the water schedule.
+
+(SELECT
+ WA.id AS animalId,
+ WA.date AS date,
+ WA.date AS dateOrdered,
+ WA.id.curLocation.area as area,
+ WA.id.curLocation.room as room,
+ WA.id.curLocation.cage as cage,
+ WA.date AS startDateCoalesced,
+ WA.date AS endDateCoalescedFuture,
+ CAST (WA.volume AS DOUBLE) AS volume,
+ WA.assignedTo AS assignedTo,
+ WA.assignedTo.title AS assignedToTitle,
+ WA.provideFruit AS provideFruit,
+ WA.provideFruit.title AS provideFruitTitle,
+ 'waterAmount' AS dataSource,
+ WA.objectid AS objectid,
+ WA.taskid AS taskid,
+ WA.lsid AS lsid,
+ WA.project AS project,
+ WA.frequency AS frequency,
+ WA.frequency.meaning AS frequencyMeaning,
+ 'PM' AS timeofday,
+ 'PM' AS displaytimeofday,
+ WA.waterSource AS waterSource,
+ true AS actionRequired,
+ WA.qcstate AS qcstate
+
+
+FROM study.waterAmount WA
+--WHERE WA.date >= curdate()
+)
+
+UNION ALL
+
+(SELECT
+ WS.animalId AS animalId,
+ WS.origDate AS origDate,
+ WS.date AS dateOrdered,
+ WS.area as area,
+ WS.room as room,
+ WS.cage as cage,
+ WS.startDate AS startDateCoalesced,
+ WS.enddateCoalescedFuture AS endDateCoalescedFuture,
+ CAST (WS.volume AS DOUBLE) AS volume,
+ WS.assignedTo AS assignedTo,
+ WS.assignedToTittle AS assignedToTitle,
+ WS.provideFruit AS provideFruit,
+ WS.provideFruitTitle AS provideFruitValue,
+ 'waterOrders' AS dataSource,
+ WS.objectid AS objectid,
+ WS.taskid AS taskid,
+ WS.lsid AS lsid,
+ WS.project AS project,
+ WS.frequency AS frequency,
+ WS.freqMeaning AS frequencyMeaning,
+ WS.timeOfDay AS timeofday,
+ WS.displaytimeofday AS displaytimeofday,
+ WS.waterSource AS waterSource,
+ (WS.waterSource = 'regulated' OR WS.startDate = WS.origDate) AS actionRequired,
+ WS.waterStatus AS qcstate
+
+
+FROM study.waterSchedule WS
+WHERE NOT EXISTS (SELECT 1
+ FROM study.waterAmount WAI
+ WHERE WAI.id = WS.animalId AND CAST(WAI.date AS TIMESTAMP) = CAST(WS.date AS TIMESTAMP)
+ --AND WAI.frequency = WS.frequency
+ )
+)
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced/.qview.xml b/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced/.qview.xml
new file mode 100644
index 000000000..a8796b847
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced/.qview.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced/Scheduled.qview.xml b/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced/Scheduled.qview.xml
new file mode 100644
index 000000000..72fc42dcf
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterScheduleCoalesced/Scheduled.qview.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterScheduledAnimalWithOutEntries.sql b/WNPRC_EHR/resources/queries/study/waterScheduledAnimalWithOutEntries.sql
new file mode 100644
index 000000000..0b71dfd1d
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterScheduledAnimalWithOutEntries.sql
@@ -0,0 +1,10 @@
+PARAMETERS(CheckDate TIMESTAMP);
+
+SELECT DISTINCT(id), CheckDate AS date FROM
+ (SELECT a.id, a.MostRecentWaterCondition FROM study.demographicsMostRecentWaterCondition a
+ WHERE NOT EXISTS (
+ SELECT 1 FROM study.waterPrePivot b
+ WHERE a.id = b.animalId AND b.date = CheckDate
+ )
+ )
+WHERE MostRecentWaterCondition = 'regulated'
\ No newline at end of file
diff --git a/WNPRC_EHR/resources/queries/study/waterScheduledAnimals.query.xml b/WNPRC_EHR/resources/queries/study/waterScheduledAnimals.query.xml
new file mode 100644
index 000000000..0772b55ee
--- /dev/null
+++ b/WNPRC_EHR/resources/queries/study/waterScheduledAnimals.query.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Start Date
+ yyyy-MM-dd
+
+
+ End Date
+ yyyy-MM-dd hh:mm
+
+
+ Condition
+
+ ehr_lookups
+ water_source
+ value
+ title
+
+
+
+