diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests.query.xml b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests.query.xml index 63925bc28..75260293e 100644 --- a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests.query.xml +++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests.query.xml @@ -19,7 +19,6 @@ Requirement Name - 250 ehr_compliancedb requirements @@ -29,7 +28,6 @@ Times Completed - 50 /query/executeQuery.view?schemaName=ehr_compliancedb& query.queryName=CompletionDates& query.EmployeeId~eq=${employeeId}& @@ -38,66 +36,52 @@ Expire Period (Months) - 70 New Expire Period (Months) - 70 Email - 70 Last Name - 110 First Name - 110 Host - 110 Supervisor - 150 Unit - 210 Most Recent Date yyyy-MM-dd - 70 Comments - 70 Category - 70 Trainee Type - 70 Requirement Name Type - 180 Months Until Renewal - 60 @@ -110,12 +94,11 @@ Essential - 60 ALWAYS_OFF Snooze Until - 60 + yyyy-MM-dd ALWAYS_OFF diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceRecentTests.query.xml b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceRecentTests.query.xml index d85eb7bac..6e634ad8b 100644 --- a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceRecentTests.query.xml +++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceRecentTests.query.xml @@ -19,7 +19,6 @@ Requirement Name - 90 ehr_compliancedb requirements @@ -29,7 +28,6 @@ Times Completed - 50 /query/executeQuery.view?schemaName=ehr_compliancedb& query.queryName=CompletionDates& query.EmployeeId~eq=${employeeId}& @@ -38,66 +36,51 @@ Expire Period (Months) - 70 New Expire Period (Months) - 70 Email - 70 - Last Name - 110 First Name - 110 Host - 110 Supervisor - 150 Unit - 210 Most Recent Date yyyy-MM-dd - 70 Comments - 70 Category - 70 Trainee Type - 70 Requirement Name Type - 180 Months Until Renewal - 60 @@ -110,12 +93,11 @@ Essential - 60 ALWAYS_OFF Snooze Until - 60 + yyyy-MM-dd ALWAYS_OFF diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt.query.xml b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt.query.xml new file mode 100644 index 000000000..7c9812b7d --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt.query.xml @@ -0,0 +1,38 @@ + + + + + Category/Unit Comparison + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt.sql b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt.sql new file mode 100644 index 000000000..65198effc --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt.sql @@ -0,0 +1,23 @@ +select a.employeeid, a.unit, null as category, a.enddate, a.lastName, a.firstName, a.email, a.type, a.title, a.category +from ehr_compliancedb.employees a +where a.unit not in (select unit from ehr_compliancedb.employeeperUnit j where j.EmployeeId = a.employeeid) +and a.unit is not null +and a.enddate is null + + + +group by a.employeeid, a.unit, a.enddate, a.lastName, a.firstName, a.email, a.type, a.title, a.category + + +union + +select a.employeeid, null as unit, a.category, a.enddate, a.lastName, + a.firstName, a.email, a.type, a.title, a.category +from ehr_compliancedb.employees a where + a.category not in (select category from ehr_compliancedb.employeeperUnit j where j.EmployeeId = a.employeeid) +and a.category is not null +and a.enddate is null + +group by a.employeeid, a.category, a.enddate, a.lastName, a.firstName, a.email, a.type, a.title, a.category + +order by a.employeeid \ No newline at end of file diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt/.qview.xml b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt/.qview.xml new file mode 100644 index 000000000..b52373e0b --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/complianceEmployeelist_rpt/.qview.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/requirements/.qview.xml b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/requirements/.qview.xml index 17d0f4476..7b0d6af85 100644 --- a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/requirements/.qview.xml +++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/requirements/.qview.xml @@ -2,7 +2,5 @@ - - - + \ No newline at end of file diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/requirements/Active.qview.xml b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/requirements/Active.qview.xml new file mode 100644 index 000000000..8c3f3c04f --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/requirements/Active.qview.xml @@ -0,0 +1,8 @@ + diff --git a/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-25.000-25.001.sql b/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-25.000-25.001.sql new file mode 100644 index 000000000..c64d1ffad --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-25.000-25.001.sql @@ -0,0 +1,579 @@ +ALTER TABLE onprc_ehr_compliancedb.ComplianceProcedureReport ALTER COLUMN expired_period varchar(50) NULL; +GO + +ALTER TABLE onprc_ehr_compliancedb.ComplianceProcedureReport ALTER COLUMN new_expired_period varchar(50) NULL; +GO + +ALTER TABLE onprc_ehr_compliancedb.ComplianceRecentReport ALTER COLUMN expired_period varchar(50) NULL; +GO + +ALTER TABLE onprc_ehr_compliancedb.ComplianceRecentReport ALTER COLUMN new_expired_period varchar(50) NULL; +GO + + + +EXEC core.fn_dropifexists 'p_ComplianceProcedureOverDueSoon_Process', 'onprc_ehr_compliancedb', 'PROCEDURE'; +GO + +-- Author: R. Blasa +-- Created: 9-20-2024 + +/* +** +** Created by +** Blasa 9-20-2024 Created a storedprocedure to create a static set of data from +** the ComplianceProcedureRecentTest.sql query +** +** 1-22-2026 Fix the issues with more than one subquery results +** +** +** +*/ + +CREATE Procedure onprc_ehr_compliancedb.p_ComplianceProcedureOverDueSoon_Process + + +AS + + + ----- Reset Reporting table + Delete onprc_ehr_compliancedb.ComplianceProcedureReport + + If @@Error <> 0 + GoTo Err_Proc + + + +BEGIN + + Insert into onprc_ehr_compliancedb.ComplianceProcedureReport + ( + requirementname, + employeeid, + unit, + category, + trackingflag, + email, + lastname, + firstname, + host, + supervisor, + trainee_type, + requirement_name_type, + times_completed, + expired_period, + new_expired_Period, + mostrecentcompleted_date, + comment, + snooze_date, + months_until_renewal + + ) + + + + + + select b.requirementname, + a.employeeid, + string_agg(a.unit,char(10)) as unit, + string_agg(a.category,char(10)) as category, + string_agg(b.trackingflag,char(10)) as trackingflag, + (select h.email from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as email, + (select h.lastname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as lastname, + (select h.firstname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as firstname, + (select h.majorudds from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as host, + (select h.supervisor from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as supervisor, + (select h.type from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as trainee_type, ----- type trainee, or trainer + (select string_agg(h.type,char(10)) from ehr_compliancedb.Requirements h where h.requirementname = b.requirementname) as requirement_type, + + (select count(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= b.requirementname and zz.employeeid= a.employeeid ) as times_Completed, + + (select string_agg(k.expireperiod,char(10)) from ehr_compliancedb.Requirements k where k.requirementname = b.requirementname) as ExpiredPeriod, + + ( select (datediff(month,max(pq.date), tt.reviewdate) ) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = b.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (COALESCE(tt.expireperiod,0)) > (datediff(month,max(pq.date), tt.reviewdate)) and (tt.reviewdate is not null) ) as NewExpirePeriod, + + (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= b.requirementname and zz.employeeid= a.employeeid ) as mostrecentcompleted_date, + + (Select distinct string_agg(yy.comment, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= b.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= b.requirementname and yy.employeeid= a.employeeid ) as comment, + + (Select distinct string_agg(yy.snooze_date, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= b.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= b.requirementname and yy.employeeid= a.employeeid ) as snooze_date, + + CAST( + CASE + + WHEN (select max(st.date) from ehr_compliancedb.completiondates st where st.requirementname = b.requirementname and st.employeeid = a.employeeid ) IS NULL then 0 + WHEN ( select (COALESCE(tt.expireperiod,0)) from ehr_compliancedb.requirements tt where tt.requirementname = b.requirementname group by tt.expireperiod ) = 0 then Null + + + WHEN ( select count(*) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = b.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) > 0 THEN + + ( select (datediff(month,max(pq.date), tt.reviewdate) - ( datediff(month,max(pq.date), getdate()) ) )from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = b.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) + + + ELSE ( select (COALESCE(tt.expireperiod,0)) - ( datediff(month,max(pq.date), getdate()) ) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = b.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod ) + + END AS Float) AS MonthsUntilRenewal + + + + from ehr_Compliancedb.employeeperunit a ,ehr_compliancedb.requirementspercategory b + where ( a.unit = b.unit or a.category = b.category ) + And b.requirementname not in (select distinct t.requirementname from ehr_compliancedb.employeerequirementexemptions t Where a.employeeid = t.employeeid + And b.requirementname = t.requirementname) + And a.employeeid in (select p.employeeid from ehr_compliancedb.employees p where a.employeeid = p.employeeid And p.enddate is null) + And b.requirementname in (select q.requirementname from ehr_compliancedb.Requirements q where q.requirementname = b.requirementname And q.dateDisabled is null ) + + + group by b.requirementname,a.employeeid + + union + + select a.requirementname, + a.employeeid, + null as unit, + null as category, + 'None' as trackingflag, + (select h.email from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as email, + (select h.lastname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as lastname, + (select h.firstname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as firstname, + (select h.majorudds from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as host, + (select h.supervisor from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as supervisor, + (select h.type from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as trainee_type, ----- type trainee, or trainer + (select string_agg(h.type,char(10))from ehr_compliancedb.Requirements h where h.requirementname = a.requirementname) as requirement_type, ----- type trainee, or trainer + + + (select count(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) as timesCompleted, + + (select string_agg(k.expireperiod,char(10)) from ehr_compliancedb.Requirements k where k.requirementname = a.requirementname) as ExpiredPeriod, + + ( select (datediff(month,max(pq.date), tt.reviewdate) )from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (COALESCE(tt.expireperiod,0)) > (datediff(month,max(pq.date), tt.reviewdate)) and (tt.reviewdate is not null) ) as NewExpirePeriod, + + (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) as MostRecentDate, + + (Select distinct string_agg(yy.comment, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= a.requirementname and yy.employeeid= a.employeeid ) as comment, + + (Select distinct string_agg(yy.snooze_date, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= a.requirementname and yy.employeeid= a.employeeid ) as snooze_date, + + CAST( + CASE + WHEN (select max(st.date) from ehr_compliancedb.completiondates st where st.requirementname = a.requirementname and st.employeeid = a.employeeid ) IS NULL then 0 + WHEN ( select (COALESCE(tt.expireperiod,0)) from ehr_compliancedb.requirements tt where tt.requirementname = a.requirementname group by tt.expireperiod ) = 0 then Null + + + WHEN ( select count(*) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) > 0 THEN + + ( select (datediff(month,max(pq.date), tt.reviewdate) - ( datediff(month,max(pq.date), getdate())) ) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) + + + ELSE ( select (COALESCE(tt.expireperiod,0)) - ( datediff(month,max(pq.date), getdate())) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod ) + + END AS FLOAT) AS MonthsUntilRenewal + + + from ehr_compliancedb.completiondates a + where a.requirementname not in (select distinct h.requirementname from ehr_compliancedb.employeeperunit k, ehr_compliancedb.requirementspercategory h Where (k.unit = h.unit + or k.category = h.category) And a.employeeid = k.employeeid ) + And a.requirementname not in (select distinct t.requirementname from ehr_compliancedb.employeerequirementexemptions t Where a.employeeid = t.employeeid + And a.requirementname = t.requirementname) + And a.employeeid in (select p.employeeid from ehr_compliancedb.employees p where a.employeeid = p.employeeid And p.enddate is null) + And a.requirementname in (select q.requirementname from ehr_compliancedb.Requirements q where q.requirementname = a.requirementname And q.dateDisabled is null ) + + group by a.requirementname,a.employeeid + + union + + -- Additional requirements for employees that have not completed training, but is required + select j.requirementname, + j.employeeid, + null as unit, + null as category, + string_agg(j.trackingflag,char(10)) as trackingflag, + (select h.email from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as email, + (select h.lastname from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as lastname, + (select h.firstname from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as firstname, + (select h.majorudds from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as host, + (select h.supervisor from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as supervisor, + (select h.type from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as trainee_type, ----- type trainee, or trainer + (select string_agg(h.type,char(10)) from ehr_compliancedb.Requirements h where h.requirementname = j.requirementname) as requirement_type, ----- type trainee, or trainer + 0 as timesCompleted, + (select string_agg(k.expireperiod,char(10)) from ehr_compliancedb.Requirements k where k.requirementname = j.requirementname) as ExpiredPeriod, + ( select (datediff(month,max(pq.date), tt.reviewdate) )from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = j.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = j.employeeid group by tt.expireperiod, tt.reviewdate + having (COALESCE(tt.expireperiod,0)) > (datediff(month,max(pq.date), tt.reviewdate)) and (tt.reviewdate is not null) ) as NewExpirePeriod, + null as MostRecentDate, + '' as comment, + null as snooze_date, + CAST( + CASE + + WHEN (select max(st.date) from ehr_compliancedb.completiondates st where st.requirementname = j.requirementname and st.employeeid = j.employeeid ) IS NULL then 0 + WHEN ( select (COALESCE(tt.expireperiod,0)) from ehr_compliancedb.requirements tt where tt.requirementname = j.requirementname group by tt.expireperiod ) = 0 then Null + + + WHEN ( select count(*) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = j.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = j.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) > 0 THEN + + ( select (datediff(month,max(pq.date), tt.reviewdate) - ( datediff(month,max(pq.date), getdate())) ) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = j.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = j.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) + + + ELSE ( select (COALESCE(tt.expireperiod,0)) - ( datediff(month,max(pq.date), getdate())) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = j.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = j.employeeid group by tt.expireperiod ) + + END AS FLOAT) AS MonthsUntilRenewal + + + + from onprc_ehr_compliancedb.RequirementsPerEmployee j + Where j.employeeid in (select p.employeeid from ehr_compliancedb.employees p where j.employeeid = p.employeeid And p.enddate is null) + And j.requirementname in (select q.requirementname from ehr_compliancedb.Requirements q where q.requirementname = j.requirementname And q.dateDisabled is null ) + And j.requirementname not in (select distinct h.requirementname from ehr_compliancedb.employeeperunit k, ehr_compliancedb.requirementspercategory h Where (k.unit = h.unit + or k.category = h.category) And j.employeeid = k.employeeid ) + And j.requirementname not in (select distinct t.requirementname from ehr_compliancedb.employeerequirementexemptions t Where j.employeeid = t.employeeid And j.requirementname = t.requirementname) + And j.requirementname not in (select distinct k.requirementname from ehr_compliancedb.completiondates k Where k.employeeid = j.employeeid) + + group by j.requirementname,j.employeeid + + order by employeeid,requirementname, mostrecentcompleted_date desc + + + If @@Error <> 0 + GoTo Err_Proc + + + + + RETURN 0 + + +Err_Proc: + + RETURN 1 + + +END + +GO + + + + +EXEC core.fn_dropifexists 'p_ComplianceRecentOverDueSoon_Process', 'onprc_ehr_compliancedb', 'PROCEDURE'; +GO + +-- Author: R. Blasa +-- Created: 9-20-2024 + +/* +** +** Created by +** Blasa 9-20-2024 Created a storedprocedure to create a static set of data from +** the ComplianceRecentTest.sql query +** +** 1-22-2026 Fix the issues with more than one subquery results +** +** +*/ + +CREATE Procedure onprc_ehr_compliancedb.p_ComplianceRecentOverDueSoon_Process + + + AS + + + +----- Reset Reporting table +Delete onprc_ehr_compliancedb.ComplianceRecentReport + + If @@Error <> 0 + GoTo Err_Proc + + + +BEGIN + +Insert into onprc_ehr_compliancedb.ComplianceRecentReport +( + requirementname, + employeeid, + unit, + category, + trackingflag, + email, + lastname, + firstname, + host, + supervisor, + trainee_type, + requirement_name_type, + times_completed, + expired_period, + new_expired_Period, + mostrecentcompleted_date, + comment, + snooze_date, + months_until_renewal + +) + + + + +select b.requirementname, + a.employeeid, + string_agg(a.unit,char(10)) as unit, + string_agg(a.category,char(10)) as category, + string_agg(b.trackingflag,char(10)) as trackingflag, + (select h.email from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as email, + (select h.lastname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as lastname, + (select h.firstname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as firstname, + (select h.majorudds from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as host, + (select h.supervisor from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as supervisor, + (select h.type from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as trainee_type, ----- type trainee, or trainer + (select string_agg(h.type,char(10)) from ehr_compliancedb.Requirements h where h.requirementname = b.requirementname) as requirement_type, ----- type trainee, or trainer + + + (select count(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= b.requirementname and zz.employeeid= a.employeeid ) as times_Completed, + + (select string_agg(k.expireperiod,char(10)) from ehr_compliancedb.Requirements k where k.requirementname = b.requirementname) as ExpiredPeriod, + + ( select (datediff(month,max(pq.date), tt.reviewdate) ) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = b.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (COALESCE(tt.expireperiod,0)) > (datediff(month,max(pq.date), tt.reviewdate)) and (tt.reviewdate is not null) ) as NewExpirePeriod, + + (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= b.requirementname and zz.employeeid= a.employeeid ) as mostrecentcompleted_date, + + (Select distinct string_agg(yy.comment, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= b.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= b.requirementname and yy.employeeid= a.employeeid ) as comment, + + (Select distinct string_agg(yy.snooze_date, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= b.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= b.requirementname and yy.employeeid= a.employeeid ) as snooze_date, + + CAST( + CASE + + WHEN (select max(st.date) from ehr_compliancedb.completiondates st where st.requirementname = b.requirementname and st.employeeid = a.employeeid ) IS NULL then 0 + WHEN ( select (COALESCE(tt.expireperiod,0)) from ehr_compliancedb.requirements tt where tt.requirementname = b.requirementname group by tt.expireperiod ) = 0 then Null + + + WHEN ( select count(*) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = b.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) > 0 THEN + + ( select (datediff(month,max(pq.date), tt.reviewdate) - ( datediff(month,max(pq.date), getdate())) ) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = b.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) + + + + + ELSE ( select (COALESCE(tt.expireperiod,0)) - ( datediff(month,max(pq.date), getdate())) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = b.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod ) + + END AS FLOAT) AS MonthsUntilRenewal + + + +from ehr_Compliancedb.employeeperunit a ,ehr_compliancedb.requirementspercategory b +where ( a.unit = b.unit or a.category = b.category ) + And b.requirementname not in (select distinct t.requirementname from ehr_compliancedb.employeerequirementexemptions t Where a.employeeid = t.employeeid + And b.requirementname = t.requirementname) + And a.employeeid in (select p.employeeid from ehr_compliancedb.employees p where a.employeeid = p.employeeid And p.enddate is null) + And b.requirementname in (select q.requirementname from ehr_compliancedb.Requirements q where q.requirementname = b.requirementname And q.dateDisabled is null ) + + +group by b.requirementname,a.employeeid + + +union + +select a.requirementname, + a.employeeid, + null as unit, + null as category, + 'None' as trackingflag, + (select h.email from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as email, + (select h.lastname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as lastname, + (select h.firstname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as firstname, + (select h.majorudds from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as host, + (select h.supervisor from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as supervisor, + (select h.type from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as trainee_type, ----- type trainee, or trainer + (select string_agg(h.type,char(10)) from ehr_compliancedb.Requirements h where h.requirementname = a.requirementname) as requirement_type, ----- type trainee, or trainer + + + (select count(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) as timesCompleted, + + (select string_agg(k.expireperiod,char(10)) from ehr_compliancedb.Requirements k where k.requirementname = a.requirementname) as ExpiredPeriod, + + ( select (datediff(month,max(pq.date), tt.reviewdate) )from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (COALESCE(tt.expireperiod,0)) > (datediff(month,max(pq.date), tt.reviewdate)) and (tt.reviewdate is not null) ) as NewExpirePeriod, + + (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) as MostRecentDate, + + (Select distinct string_agg(yy.comment, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= a.requirementname and yy.employeeid= a.employeeid ) as comment, + + (Select distinct string_agg(yy.snooze_date, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= a.requirementname and yy.employeeid= a.employeeid ) as snooze_date, + + CAST( + CASE + WHEN (select max(st.date) from ehr_compliancedb.completiondates st where st.requirementname = a.requirementname and st.employeeid = a.employeeid ) IS NULL then 0 + WHEN ( select (COALESCE(tt.expireperiod,0)) from ehr_compliancedb.requirements tt where tt.requirementname = a.requirementname group by tt.expireperiod ) = 0 then Null + + + WHEN ( select count(*) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) > 0 THEN + + ( select (datediff(month,max(pq.date), tt.reviewdate) - ( datediff(month,max(pq.date), getdate())) ) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) + + + ELSE ( select (COALESCE(tt.expireperiod,0)) - ( datediff(month,max(pq.date), getdate())) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod ) + + END AS FLOAT) AS MonthsUntilRenewal + + +from ehr_compliancedb.completiondates a +where a.requirementname not in (select distinct h.requirementname from ehr_compliancedb.employeeperunit k, ehr_compliancedb.requirementspercategory h Where (k.unit = h.unit + or k.category = h.category) And a.employeeid = k.employeeid ) + And a.requirementname not in (select distinct t.requirementname from ehr_compliancedb.employeerequirementexemptions t Where a.employeeid = t.employeeid + And a.requirementname = t.requirementname) + And a.employeeid in (select p.employeeid from ehr_compliancedb.employees p where a.employeeid = p.employeeid And p.enddate is null) + And a.requirementname in (select q.requirementname from ehr_compliancedb.Requirements q where q.requirementname = a.requirementname And q.dateDisabled is null ) + +group by a.requirementname,a.employeeid + +UNION + +--- Training that was completed by as an employee training exemptions, and at least completed one, or more times + +select a.requirementname, + a.employeeid, + null as unit, + null as category, + 'No' as trackingflag, + (select h.email from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as email, + (select h.lastname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as lastname, + (select h.firstname from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as firstname, + (select h.majorudds from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as host, + (select h.supervisor from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as supervisor, + (select h.type from ehr_compliancedb.employees h where h.employeeid = a.employeeid) as trainee_type, ----- type trainee, or trainer + (select string_agg(h.type,char(10)) from ehr_compliancedb.Requirements h where h.requirementname = a.requirementname) as requirement_type, ----- type trainee, or trainer + + + (select count(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) as timesCompleted, + + (select string_agg(k.expireperiod,char(10)) from ehr_compliancedb.Requirements k where k.requirementname = a.requirementname) as ExpiredPeriod, + + ( select (datediff(month,max(pq.date), tt.reviewdate) )from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (COALESCE(tt.expireperiod,0)) > (datediff(month,max(pq.date), tt.reviewdate)) and (tt.reviewdate is not null) ) as NewExpirePeriod, + + (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) as MostRecentDate, + + (Select distinct string_agg(yy.comment, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= a.requirementname and yy.employeeid= a.employeeid ) as comment, + + (Select distinct string_agg(yy.snooze_date, char(10)) from ehr_compliancedb.completiondates yy where yy.date in (select max(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= a.requirementname and zz.employeeid= a.employeeid ) + And yy.requirementname= a.requirementname and yy.employeeid= a.employeeid ) as snooze_date, + + CAST( + CASE + WHEN (select max(st.date) from ehr_compliancedb.completiondates st where st.requirementname = a.requirementname and st.employeeid = a.employeeid ) IS NULL then 0 + WHEN ( select (COALESCE(tt.expireperiod,0)) from ehr_compliancedb.requirements tt where tt.requirementname = a.requirementname group by tt.expireperiod ) = 0 then Null + + + WHEN ( select count(*) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) > 0 THEN + + ( select ( datediff(month,max(pq.date), tt.reviewdate) - (datediff(month,max(pq.date), getdate())) )from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) + + + ELSE ( select (COALESCE(tt.expireperiod,0)) - ( datediff(month,max(pq.date), getdate())) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = a.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = a.employeeid group by tt.expireperiod ) + + END AS DECIMAL) AS MonthsUntilRenewal + + +from ehr_compliancedb.employeerequirementexemptions a +Where a.employeeid in (select p.employeeid from ehr_compliancedb.employees p where a.employeeid = p.employeeid And p.enddate is null) + And a.requirementname in (select q.requirementname from ehr_compliancedb.Requirements q where q.requirementname = a.requirementname And q.dateDisabled is null ) + +group by a.requirementname,a.employeeid + +UNION + +--- Additional requirements for employees that have not completed training, but is required + +select j.requirementname, + j.employeeid, + null as unit, + null as category, + string_agg(j.trackingflag,char(10)) as trackingflag, + (select h.email from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as email, + (select h.lastname from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as lastname, + (select h.firstname from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as firstname, + (select h.majorudds from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as host, + (select h.supervisor from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as supervisor, + (select h.type from ehr_compliancedb.employees h where h.employeeid = j.employeeid) as trainee_type, ----- type trainee, or trainer + (select string_agg(h.type,char(10)) from ehr_compliancedb.Requirements h where h.requirementname = j.requirementname) as requirement_type, ----- type trainee, or trainer + 0 as timesCompleted, + (select string_agg(k.expireperiod,char(10)) from ehr_compliancedb.Requirements k where k.requirementname = j.requirementname) as ExpiredPeriod, + ( select (datediff(month,max(pq.date), tt.reviewdate) )from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = j.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = j.employeeid group by tt.expireperiod, tt.reviewdate + having (COALESCE(tt.expireperiod,0)) > (datediff(month,max(pq.date), tt.reviewdate)) and (tt.reviewdate is not null) ) as NewExpirePeriod, + null as MostRecentDate, + '' as comment, + null as snooze_date, + CAST( + CASE + + WHEN (select max(st.date) from ehr_compliancedb.completiondates st where st.requirementname = j.requirementname and st.employeeid = j.employeeid ) IS NULL then 0 + WHEN ( select (COALESCE(tt.expireperiod,0)) from ehr_compliancedb.requirements tt where tt.requirementname = j.requirementname group by tt.expireperiod ) = 0 then Null + + WHEN ( select count(*) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = j.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = j.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) > 0 THEN + + ( select (datediff(month,max(pq.date), tt.reviewdate) - ( datediff(month,max(pq.date), getdate())) ) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = j.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = j.employeeid group by tt.expireperiod, tt.reviewdate + having (tt.reviewdate) > (max(pq.date)) ) + + + ELSE ( select (COALESCE(tt.expireperiod,0)) - ( datediff(month,max(pq.date), getdate())) from ehr_compliancedb.requirements tt, ehr_compliancedb.completiondates pq where tt.requirementname = j.requirementname and pq.requirementname = tt.requirementname and pq.employeeid = j.employeeid group by tt.expireperiod ) + + END AS FLOAT) AS MonthsUntilRenewal + + +from onprc_ehr_compliancedb.RequirementsPerEmployee j +Where j.employeeid in (select p.employeeid from ehr_compliancedb.employees p where j.employeeid = p.employeeid And p.enddate is null) + And j.requirementname in (select q.requirementname from ehr_compliancedb.Requirements q where q.requirementname = j.requirementname And q.dateDisabled is null ) + And j.requirementname not in (select distinct h.requirementname from ehr_compliancedb.employeeperunit k, ehr_compliancedb.requirementspercategory h Where (k.unit = h.unit + or k.category = h.category) And j.employeeid = k.employeeid ) + And j.requirementname not in (select distinct t.requirementname from ehr_compliancedb.employeerequirementexemptions t Where j.employeeid = t.employeeid And j.requirementname = t.requirementname) + And j.requirementname not in (select distinct k.requirementname from ehr_compliancedb.completiondates k Where k.employeeid = j.employeeid) + +group by j.requirementname,j.employeeid + +order by employeeid,requirementname, mostrecentcompleted_date desc + + + If @@Error <> 0 + GoTo Err_Proc + + + + + RETURN 0 + + +Err_Proc: + + RETURN 1 + + +END + +GO \ No newline at end of file diff --git a/ONPRC_EHR_ComplianceDB/resources/views/begin.html b/ONPRC_EHR_ComplianceDB/resources/views/begin.html index 6712a429e..73efe6821 100644 --- a/ONPRC_EHR_ComplianceDB/resources/views/begin.html +++ b/ONPRC_EHR_ComplianceDB/resources/views/begin.html @@ -92,6 +92,8 @@ name: 'List of Unused Training Names', url: ctx['SSRSServerURL'] +'%2fPrime+Reports%2fCompliance%2fCompliance_Unassigned_requirements&rs:Command=Render' },{ name: 'List of Duplicate Completion Dates', url: ctx['SSRSServerURL'] +'%2fPrime+Reports%2fCompliance%2fCompliance_Duplicate_CompletedDates&rs:Command=Render' + },{ + name: 'Category/Unit Comparison', url: '<%=contextPath%>/query' + container + '/executeQuery.view?schemaName=ehr_compliancedb&query.queryName=complianceEmployeelist_rpt' }] },{ diff --git a/ONPRC_EHR_ComplianceDB/resources/views/employeeDetails.html b/ONPRC_EHR_ComplianceDB/resources/views/employeeDetails.html new file mode 100644 index 000000000..d5de04cf2 --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/views/employeeDetails.html @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/ONPRC_EHR_ComplianceDB/resources/views/employeeDetails.view.xml b/ONPRC_EHR_ComplianceDB/resources/views/employeeDetails.view.xml new file mode 100644 index 000000000..ab66d427b --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/views/employeeDetails.view.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ONPRC_EHR_ComplianceDB/resources/web/EHR_ComplianceDB/panel/EmployeeDetailsPanel.js b/ONPRC_EHR_ComplianceDB/resources/web/EHR_ComplianceDB/panel/EmployeeDetailsPanel.js new file mode 100644 index 000000000..f0ae92228 --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/web/EHR_ComplianceDB/panel/EmployeeDetailsPanel.js @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013-2019 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +/** + * @cfg employeeId + * @cfg schemaName + */ +Ext4.define('EHR_ComplianceDB.panel.EmployeeDetailsPanel', { + extend: 'Ext.panel.Panel', + schemaName: 'ehr_complianceDB', + + initComponent: function(){ + var filterArray = [LABKEY.Filter.create('employeeid', this.employeeId, LABKEY.Filter.Types.EQUAL)]; + + Ext4.apply(this, { + border: false, + defaults: { + border: false, + style: 'margin-bottom: 20px;' + }, + items: [{ + xtype: 'ldk-detailspanel', + store: { + schemaName: this.schemaName, + queryName: 'employees', + filterArray: filterArray + }, + showBackBtn: false, + title: 'Employee Details' + }, { + xtype: 'ldk-querypanel', + queryConfig: { + title: 'Training / Requirement Summary', + schemaName: this.schemaName, + queryName: 'ComplianceProcedureRecentTests', //exclude employee training exemptions + filterArray: filterArray, + failure: LDK.Utils.getErrorCallback() + } + },{ + xtype: 'ldk-querypanel', + queryConfig: { + title: 'Exemptions From Training Requirements', + schemaName: this.schemaName, + queryName: 'employeerequirementexemptions', + filterArray: filterArray, + failure: LDK.Utils.getErrorCallback() + } + },{ + xtype: 'ldk-querypanel', + queryConfig: { + title: 'Training History', + schemaName: this.schemaName, + queryName: 'completionDates', + filterArray: filterArray, + failure: LDK.Utils.getErrorCallback() + } + }] + }); + + this.callParent(); + } +}); \ No newline at end of file diff --git a/ONPRC_EHR_ComplianceDB/src/org/labkey/ONPRCEHR_ComplianceDB/ONPRC_EHR_ComplianceDBModule.java b/ONPRC_EHR_ComplianceDB/src/org/labkey/ONPRCEHR_ComplianceDB/ONPRC_EHR_ComplianceDBModule.java index ffa8320d2..e03bd4352 100644 --- a/ONPRC_EHR_ComplianceDB/src/org/labkey/ONPRCEHR_ComplianceDB/ONPRC_EHR_ComplianceDBModule.java +++ b/ONPRC_EHR_ComplianceDB/src/org/labkey/ONPRCEHR_ComplianceDB/ONPRC_EHR_ComplianceDBModule.java @@ -55,7 +55,7 @@ public String getName() @Override public Double getSchemaVersion() { - return 24.012; + return 25.001; } //Modified: 9-8-025 @Override @@ -110,7 +110,8 @@ protected void doStartupAfterSpringConfig(ModuleContext moduleContext) // Added: 10-24-2022 R.Blasa EHRService.get().registerMoreActionsButton(new ShowEditUIButton(this, "ehr_compliancedb", "completiondates", ONPRC_ComplianceDBEntryPermission.class), "ehr_compliancedb", "completiondates"); - + // Added 1-8-2026 + EHRService.get().registerActionOverride("employeeDetails", this, "employeeDetails.html"); } diff --git a/onprc_billing/resources/queries/onprc_billing/chargeRates.js b/onprc_billing/resources/queries/onprc_billing/chargeRates.js index 3ee20ddab..0b8f87628 100644 --- a/onprc_billing/resources/queries/onprc_billing/chargeRates.js +++ b/onprc_billing/resources/queries/onprc_billing/chargeRates.js @@ -16,10 +16,18 @@ function beforeUpdate(row, errors){ function beforeUpsert(row, errors){ if (row.startDate){ + // normalize to date-only (00:00) row.startDate = ldkUtils.removeTimeFromDate(row.startDate); } if (row.endDate){ - row.endDate = ldkUtils.removeTimeFromDate(row.endDate); + // normalize to date-only first + var cleanDate = ldkUtils.removeTimeFromDate(row.endDate); + + // create a new date object set to 23:59 + var endOfDay = new Date(cleanDate); + endOfDay.setHours(23, 59, 0, 0); + + row.endDate = endOfDay; } } \ No newline at end of file diff --git a/onprc_billing/resources/queries/onprc_billing/chargeRates/Active Rates.qview.xml b/onprc_billing/resources/queries/onprc_billing/chargeRates/Active Rates.qview.xml index 4453d5cc3..6cba0006d 100644 --- a/onprc_billing/resources/queries/onprc_billing/chargeRates/Active Rates.qview.xml +++ b/onprc_billing/resources/queries/onprc_billing/chargeRates/Active Rates.qview.xml @@ -4,6 +4,6 @@ - + \ No newline at end of file diff --git a/onprc_billing/resources/queries/onprc_billing/miscCharges.query.xml b/onprc_billing/resources/queries/onprc_billing/miscCharges.query.xml index 7b284cbb5..09f09c99f 100644 --- a/onprc_billing/resources/queries/onprc_billing/miscCharges.query.xml +++ b/onprc_billing/resources/queries/onprc_billing/miscCharges.query.xml @@ -16,7 +16,7 @@ core qcstate rowid - +
Charge Unit @@ -27,6 +27,17 @@ + + Source Transaction + false + + /ONPRC/Admin/Finance + onprc_billing + invoicedItems + objectid + transactionNumber + + onprc_billing diff --git a/onprc_billing/resources/schemas/onprc_billing.xml b/onprc_billing/resources/schemas/onprc_billing.xml index 2bb09f73b..596aba084 100644 --- a/onprc_billing/resources/schemas/onprc_billing.xml +++ b/onprc_billing/resources/schemas/onprc_billing.xml @@ -419,10 +419,11 @@ Source Transaction true + /ONPRC/Admin/Finance onprc_billing invoicedItems objectid - rowid + transactionNumber @@ -1152,11 +1153,11 @@ OGA Grant Number - + Agency Award Number - + Investigator @@ -1641,4 +1642,4 @@ - \ No newline at end of file + diff --git a/onprc_billing/resources/web/onprc_billing/window/ReverseChargeWindow.js b/onprc_billing/resources/web/onprc_billing/window/ReverseChargeWindow.js index fb7058865..5691d0a26 100644 --- a/onprc_billing/resources/web/onprc_billing/window/ReverseChargeWindow.js +++ b/onprc_billing/resources/web/onprc_billing/window/ReverseChargeWindow.js @@ -681,4 +681,4 @@ Ext4.define('ONPRC_Billing.window.ReverseChargeWindow', { } }); } -}); \ No newline at end of file +}); diff --git a/onprc_billing/src/org/labkey/onprc_billing/table/ONPRC_BillingCustomizer.java b/onprc_billing/src/org/labkey/onprc_billing/table/ONPRC_BillingCustomizer.java index 3c678ea9d..804757c78 100644 --- a/onprc_billing/src/org/labkey/onprc_billing/table/ONPRC_BillingCustomizer.java +++ b/onprc_billing/src/org/labkey/onprc_billing/table/ONPRC_BillingCustomizer.java @@ -180,8 +180,17 @@ private void addTotalCost(AbstractTableInfo ti) if (ti.getColumn("totalCost") == null && unitCost != null && ti.getColumn("quantity") != null) { - SQLFragment sql = new SQLFragment("(" + ExprColumn.STR_TABLE_ALIAS + ".unitCost * " + ExprColumn.STR_TABLE_ALIAS + ".quantity)"); - ExprColumn totalCost = new ExprColumn(ti, "totalCost", sql, JdbcType.DOUBLE, ti.getColumn("unitCost"), ti.getColumn("quantity")); + SQLFragment sql = new SQLFragment( + "CAST(ROUND((" + ExprColumn.STR_TABLE_ALIAS + ".unitCost * " + + ExprColumn.STR_TABLE_ALIAS + ".quantity), 2) AS DECIMAL(18,2))"); + ExprColumn totalCost = new ExprColumn( + ti, + "totalCost", + sql, + JdbcType.DECIMAL, + ti.getColumn("unitCost"), + ti.getColumn("quantity") + ); totalCost.setLabel("Total Cost"); totalCost.setFormat("$###,##0.00"); ti.addColumn(totalCost); diff --git a/onprc_ehr/resources/etls/clinPathDateFinalized.xml b/onprc_ehr/resources/etls/clinPathDateFinalized.xml new file mode 100644 index 000000000..0b49d7268 --- /dev/null +++ b/onprc_ehr/resources/etls/clinPathDateFinalized.xml @@ -0,0 +1,21 @@ + + + + + clinPathRunDateFinalized + + Clin Path Runs ensure that QCState Completed generated the Date Finalized + + + Runs Stored Procedure that checks if the Date Finalized in present for finalized Charges + + + + + + + + + + + diff --git a/onprc_ehr/resources/queries/onprc_ehr/MedsEndDateAlert.sql b/onprc_ehr/resources/queries/onprc_ehr/MedsEndDateAlert.sql index 196f647b5..a6dc2db26 100644 --- a/onprc_ehr/resources/queries/onprc_ehr/MedsEndDateAlert.sql +++ b/onprc_ehr/resources/queries/onprc_ehr/MedsEndDateAlert.sql @@ -6,6 +6,9 @@ Added these two Diets to the list by Kollil on 4/15/25. Refer to tkt #12363 3. E-X0500 - Diet, L-Phyto (Low-phytoestrogen) 4. E-Y9750 - Diet, 5047 High Protein, Jumbo + + Added Diet to the list by Kollil on 5/14/25. Refer to tkt #12506 +5. E-X1380 - Diet Daily (Non-standard), 5LOP (TAD) */ SELECT Id, @@ -27,5 +30,5 @@ SELECT category, taskid.rowid as TaskId FROM study.treatment_order -WHERE code NOT IN ('E-85760', 'E-Y7735', 'E-X0500', 'E-Y9750') +WHERE code NOT IN ('E-85760', 'E-Y7735', 'E-X0500', 'E-Y9750', 'E-X1380') AND enddate is null \ No newline at end of file diff --git a/onprc_ehr/resources/queries/onprc_ehr/NewBirthTasks.query.xml b/onprc_ehr/resources/queries/onprc_ehr/NewBirthTasks.query.xml new file mode 100644 index 000000000..d12c41f86 --- /dev/null +++ b/onprc_ehr/resources/queries/onprc_ehr/NewBirthTasks.query.xml @@ -0,0 +1,54 @@ + + + + + New Birth tasks created in last 7 days + + + Task ID + /ehr/dataEntryForm.view?formType=${formtype}&taskid=${taskid} + + + Title + + + Task Type + + + Assigned To + true + + core + PrincipalsWithoutAdmin + UserId + + + + Due Date + true + yyyy-MM-dd HH:mm + + + Created By + + core + users + userid + + + + Created + true + yyyy-MM-dd HH:mm + + + Status + false + true + 50 + + +
+
+
+
diff --git a/onprc_ehr/resources/queries/onprc_ehr/NewBirthTasks.sql b/onprc_ehr/resources/queries/onprc_ehr/NewBirthTasks.sql new file mode 100644 index 000000000..841349e66 --- /dev/null +++ b/onprc_ehr/resources/queries/onprc_ehr/NewBirthTasks.sql @@ -0,0 +1,21 @@ +/** + * Created by Kollil, 10/25 + * Get a list of tasks daily on a rolling 7 day window to review for QC. + * This will allow techs to see what new IDs were created by whom, and review for accuracy, + * housing history, group ids and flags. + * Refer tkt # 13504 + */ +SELECT + t.taskid, + t.title, + t.formType as TaskType, + t.assignedto, + t.duedate, + t.createdby, + t.created, + t.qcstate as Status +FROM ehr.tasks t +WHERE t.created >= TIMESTAMPADD('day', -7, NOW()) +And t.formtype = 'birth' + + diff --git a/onprc_ehr/resources/queries/study/AssignmentPoolUnderTheAge.query.xml b/onprc_ehr/resources/queries/study/AssignmentPoolUnderTheAge.query.xml new file mode 100644 index 000000000..2d839c69e --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentPoolUnderTheAge.query.xml @@ -0,0 +1,10 @@ + + + + + + Animals under the age of 3 with an assignment pool note +
+
+
+
diff --git a/onprc_ehr/resources/queries/study/AssignmentPoolUnderTheAge.sql b/onprc_ehr/resources/queries/study/AssignmentPoolUnderTheAge.sql new file mode 100644 index 000000000..da5ff511a --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentPoolUnderTheAge.sql @@ -0,0 +1,56 @@ +/* Added by Kollil, Jan 2026 + Refer to tkt # 14056 + - Extract animals under the age of 2.5 with an "Assignment pool" note in PRIMe (under general>notes) + */ + +SELECT + a.Id, + a.Id.demographics.gender AS Sex, + a.Id.Age.ageinyears, + a.Id.curlocation.room AS Room, + a.Id.curlocation.cage AS Cage, + /* Display the (active) Notes Pertaining to DAR note text */ + ( + SELECT MAX(n.value) + FROM study.Notes n + WHERE n.Id = a.Id + AND n.category = 'Notes Pertaining to DAR' + AND n.endDate IS NULL + ) AS Notes_Pertaining_to_DAR, + /* Concatenate all active cagemate IDs into one cell */ + ( + SELECT GROUP_CONCAT(DISTINCT CAST(h.roommateId AS VARCHAR), ', ') + FROM housingRoommatesDivider h + WHERE h.Id = a.Id + AND h.removalDate IS NULL + AND h.roommateEnd IS NULL + AND h.roommateId IS NOT NULL + ) AS Cagemates, + /* Concatenate all active projects & investigator into one cell */ + ( + SELECT GROUP_CONCAT(DISTINCT CAST('[' + d.project.protocol.investigatorId.lastname + ']' + d.project.displayname + '' AS VARCHAR), ', ') + FROM housingRoommatesDivider h + LEFT JOIN study.assignment d ON d.Id = h.roommateId + WHERE h.Id = a.Id + AND h.removalDate IS NULL + AND h.roommateEnd IS NULL + AND h.roommateId IS NOT NULL + AND d.enddate IS NULL + AND d.isActive = 1 + AND d.project.displayname NOT IN ('0492-02', '0492-03') + ) AS Cagemate_Assignments + +FROM Assignment a +WHERE + a.Id.Age.ageinyears <= 3 + AND a.project.displayname NOT IN ('0492-02', '0492-03') + AND a.Id.demographics.species = 'Rhesus Macaque' + AND EXISTS ( + SELECT 1 + FROM study.Notes n + WHERE n.Id = a.Id + AND n.value LIKE '%Assignment pool%' + AND n.endDate IS NULL + ) + + diff --git a/onprc_ehr/resources/queries/study/AssignmentsCreatedInPast1Day.query.xml b/onprc_ehr/resources/queries/study/AssignmentsCreatedInPast1Day.query.xml new file mode 100644 index 000000000..e5f63127d --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsCreatedInPast1Day.query.xml @@ -0,0 +1,10 @@ + + + + + + Assignments created in the past 24 hrs +
+
+
+
diff --git a/onprc_ehr/resources/queries/study/AssignmentsCreatedInPast1Day.sql b/onprc_ehr/resources/queries/study/AssignmentsCreatedInPast1Day.sql new file mode 100644 index 000000000..152a69e82 --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsCreatedInPast1Day.sql @@ -0,0 +1,23 @@ +/* Created by Kollil, Dec, 2025 + Tkt # 13618 + Priority 1: Add Grid 1 ("Assignments Created in the Past Day ") to daily Behavior Alerts email - display full grid in email + */ +SELECT + Id, + Id.demographics.gender as Sex, + Id.curlocation.room as Room, + Id.curlocation.cage as Cage, + project.displayname as project, + project.protocol.displayname as Protocol, + project.title as Title, + project.protocol.investigatorId.lastname as ProjectInvestigator, + CAST(date AS DATE) AS AssignDate, + CAST(enddate AS DATE) AS ReleaseDate, + CAST(projectedRelease AS DATE) AS ProjectedReleaseDate, + assignmentType, + assignCondition.meaning as AssignCondition, + projectedReleaseCondition.meaning as ProjectedReleaseCondition, + releaseCondition.meaning as ConditionAtRelease + +FROM Assignment +WHERE CAST(created AS DATE) >= TIMESTAMPADD('SQL_TSI_DAY', -1, CAST(NOW() AS DATE)) \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/AssignmentsReleasedInPast1Day.query.xml b/onprc_ehr/resources/queries/study/AssignmentsReleasedInPast1Day.query.xml new file mode 100644 index 000000000..40c848da0 --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsReleasedInPast1Day.query.xml @@ -0,0 +1,10 @@ + + + + + + Assignments released in the past 24 hrs +
+
+
+
diff --git a/onprc_ehr/resources/queries/study/AssignmentsReleasedInPast1Day.sql b/onprc_ehr/resources/queries/study/AssignmentsReleasedInPast1Day.sql new file mode 100644 index 000000000..2c530c3ef --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsReleasedInPast1Day.sql @@ -0,0 +1,30 @@ +/* Created by Kollil, Dec, 2025 + Tkt # 13618 + Priority 2: Create new Grid 2 (Assignments ended in the Past 1 Day): + - List of records with new “Release date” added within the last 24hrs (omitting day leases). I am not omitting day leases for now as per Isabel's request. +*/ +SELECT + Id, + Id.demographics.gender as Sex, + Id.curlocation.room as Room, + Id.curlocation.cage as Cage, + project.displayname as project, + project.protocol.displayname as Protocol, + project.title as Title, + project.protocol.investigatorId.lastname as ProjectInvestigator, + CAST(date AS DATE) AS AssignDate, + CAST(enddate AS DATE) AS ReleaseDate, + CAST(projectedRelease AS DATE) AS ProjectedReleaseDate, + assignmentType, + assignCondition.meaning as AssignCondition, + projectedReleaseCondition.meaning as ProjectedReleaseCondition, + releaseCondition.meaning as ConditionAtRelease + +FROM Assignment +/* this condition: >= TIMESTAMPADD('SQL_TSI_DAY', -1, NOW()) → not older than 24 hours +and this one: <= NOW() → not in the future +Together, they produce exactly the last 24 hours, nothing more. + */ +WHERE CAST(enddate AS DATE) = TIMESTAMPADD('SQL_TSI_DAY', -1, CAST(NOW() AS DATE)) + AND CAST(enddate AS DATE) <= CAST(NOW() AS DATE) + AND Id.demographics.calculated_status = 'Alive' \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/AssignmentsStartedPast1to7Days.query.xml b/onprc_ehr/resources/queries/study/AssignmentsStartedPast1to7Days.query.xml new file mode 100644 index 000000000..d543e5816 --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsStartedPast1to7Days.query.xml @@ -0,0 +1,10 @@ + + + + + + Assignments started in the past 1-7 days +
+
+
+
\ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/AssignmentsStartedPast1to7Days.sql b/onprc_ehr/resources/queries/study/AssignmentsStartedPast1to7Days.sql new file mode 100644 index 000000000..1702ede9b --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsStartedPast1to7Days.sql @@ -0,0 +1,31 @@ +/* Created by Kollil, Dec, 2025 + Tkt # 13618 + Priority 4: Add links to grids 3 and 4 in daily Behavior Alerts email (do not need to display full grid in email) + - for grid 3 - There were __ assignments started in the past 1-7 days" with a link, including today's date + + */ +SELECT + Id, + Id.demographics.gender as Sex, + Id.curlocation.room as Room, + Id.curlocation.cage as Cage, + project.displayname as project, + project.protocol.displayname as Protocol, + project.title as Title, + project.protocol.investigatorId.lastname as ProjectInvestigator, + CAST(date AS DATE) AS AssignDate, + CAST(enddate AS DATE) AS ReleaseDate, + CAST(projectedRelease AS DATE) AS ProjectedReleaseDate, + assignmentType, + assignCondition.meaning as AssignCondition, + projectedReleaseCondition.meaning as ProjectedReleaseCondition, + releaseCondition.meaning as ConditionAtRelease + +FROM Assignment +--including today +WHERE CAST(date AS DATE) >= TIMESTAMPADD('SQL_TSI_DAY', -7, CAST(NOW() AS DATE)) + AND CAST(date AS DATE) <= CAST(NOW() AS DATE); +--excluding today +-- WHERE CAST(date AS DATE) >= TIMESTAMPADD('SQL_TSI_DAY', -1, NOW()) +-- AND CAST(date AS DATE) < TIMESTAMPADD('SQL_TSI_DAY', -7, NOW()) + diff --git a/onprc_ehr/resources/queries/study/AssignmentsStartingNext1to14Days.query.xml b/onprc_ehr/resources/queries/study/AssignmentsStartingNext1to14Days.query.xml new file mode 100644 index 000000000..bde8b09e6 --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsStartingNext1to14Days.query.xml @@ -0,0 +1,10 @@ + + + + + + Assignments starting in the next 1 to 14 days +
+
+
+
diff --git a/onprc_ehr/resources/queries/study/AssignmentsStartingNext1to14Days.sql b/onprc_ehr/resources/queries/study/AssignmentsStartingNext1to14Days.sql new file mode 100644 index 000000000..3dc0e61c6 --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsStartingNext1to14Days.sql @@ -0,0 +1,26 @@ +/* Created by Kollil, Dec, 2025 + Tkt # 13618 + Priority 4: Add links to grids 3 and 4 in daily Behavior Alerts email (do not need to display full grid in email) + - for grid 4 - There are __ assignments starting in the Next 1-14 days" with a link, including today's date +*/ + +SELECT + Id, + Id.demographics.gender as Sex, + Id.curlocation.room as Room, + Id.curlocation.cage as Cage, + project.displayname as project, + project.protocol.displayname as Protocol, + project.title as Title, + project.protocol.investigatorId.lastname as ProjectInvestigator, + CAST(date AS DATE) AS AssignDate, + CAST(enddate AS DATE) AS ReleaseDate, + CAST(projectedRelease AS DATE) AS ProjectedReleaseDate, + assignmentType, + assignCondition.meaning as AssignCondition, + projectedReleaseCondition.meaning as ProjectedReleaseCondition, + releaseCondition.meaning as ConditionAtRelease + +FROM Assignment +WHERE CAST(date AS DATE) >= TIMESTAMPADD('SQL_TSI_DAY', 1, CAST(NOW() AS DATE)) + AND CAST(date AS DATE) <= TIMESTAMPADD('SQL_TSI_DAY', 14, CAST(NOW() AS DATE)) \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/AssignmentsUnderTheAge.query.xml b/onprc_ehr/resources/queries/study/AssignmentsUnderTheAge.query.xml new file mode 100644 index 000000000..9636deb96 --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsUnderTheAge.query.xml @@ -0,0 +1,10 @@ + + + + + + Animals under the age of 3 with an active assignment +
+
+
+
diff --git a/onprc_ehr/resources/queries/study/AssignmentsUnderTheAge.sql b/onprc_ehr/resources/queries/study/AssignmentsUnderTheAge.sql new file mode 100644 index 000000000..2f5234fdb --- /dev/null +++ b/onprc_ehr/resources/queries/study/AssignmentsUnderTheAge.sql @@ -0,0 +1,102 @@ +/* Added by Kollil, Jan 2026 + Refer to tkt # 14056 + - Extract animals under the age of 2.5 with an active assignment. Exclude the U42 and U42E colony maintenance assignments, i.e, center projects for these are 0492-02 and 0492-03. + */ + SELECT + a.Id, + a.Id.demographics.gender AS Sex, + a.Id.Age.ageinyears, + a.Id.curlocation.room AS Room, + a.Id.curlocation.cage AS Cage, + a.project, + a.project.protocol.displayname AS Protocol, + a.project.title AS Title, + a.project.protocol.investigatorId.lastname AS ProjectInvestigator, + CAST(a.date AS DATE) AS AssignDate, + CAST(a.enddate AS DATE) AS ReleaseDate, + CAST(a.projectedRelease AS DATE) AS ProjectedReleaseDate, + a.assignmentType, + a.projectedReleaseCondition.meaning AS ProjectedReleaseCondition, + a.releaseCondition.meaning AS ConditionAtRelease, + /* Concatenate all active cagemate IDs into one cell */ + ( + SELECT GROUP_CONCAT(DISTINCT CAST(h.roommateId AS VARCHAR), ', ') + FROM housingRoommatesDivider h + WHERE h.Id = a.Id + AND h.removalDate IS NULL + AND h.roommateEnd IS NULL + AND h.roommateId IS NOT NULL + ) AS Cagemates, + /* Concatenate all active projects & investigator into one cell */ + ( + SELECT GROUP_CONCAT(DISTINCT CAST('[' + d.project.protocol.investigatorId.lastname + ']' + d.project.displayname + '' AS VARCHAR), ', ') + FROM housingRoommatesDivider h + LEFT JOIN study.assignment d ON d.Id = h.roommateId + WHERE h.Id = a.Id + AND h.removalDate IS NULL + AND h.roommateEnd IS NULL + AND h.roommateId IS NOT NULL + AND d.enddate IS NULL + AND d.isActive = 1 + AND d.project.displayname NOT IN ('0492-02', '0492-03') + ) AS Cagemate_Assignments + +FROM Assignment a +WHERE + a.Id.Age.ageinyears <= 3 + AND a.Id.demographics.species = 'Rhesus Macaque' + AND a.enddate IS NULL + AND a.isActive = 1 + AND a.project.displayname NOT IN ('0492-02', '0492-03') + + + + + + + + + + + + + + + + + + + + + +-- SELECT +-- a.Id, +-- a.Id.demographics.gender AS Sex, +-- a.Id.Age.ageinyears, +-- a.Id.curlocation.room AS Room, +-- a.Id.curlocation.cage AS Cage, +-- a.project, +-- a.project.protocol.displayname AS Protocol, +-- a.project.title AS Title, +-- a.project.protocol.investigatorId.lastname AS ProjectInvestigator, +-- CAST(a.date AS DATE) AS AssignDate, +-- CAST(a.enddate AS DATE) AS ReleaseDate, +-- CAST(a.projectedRelease AS DATE) AS ProjectedReleaseDate, +-- a.assignmentType, +-- a.projectedReleaseCondition.meaning AS ProjectedReleaseCondition, +-- a.releaseCondition.meaning AS ConditionAtRelease, +-- h.roommateId AS Cagemate, +-- d.use AS Cagemate_Assignment +-- FROM Assignment a +-- LEFT JOIN housingRoommatesDivider h +-- ON h.Id = a.Id +-- AND h.removalDate IS NULL +-- AND h.roommateEnd IS NULL +-- LEFT JOIN study.demographicsUtilization d +-- ON d.Id = h.roommateId +-- WHERE +-- a.Id.Age.ageinyears <= 2.5 +-- AND a.Id.demographics.species = 'Rhesus Macaque' +-- AND a.enddate IS NULL +-- AND a.isActive = 1 +-- AND a.project.displayname NOT IN ('0492-02', '0492-03') 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/resources/queries/study/TissueDistributionSummaryCalendarYr.query.xml b/onprc_ehr/resources/queries/study/TissueDistributionSummaryCalendarYr.query.xml index a33c892f9..6208d338d 100644 --- a/onprc_ehr/resources/queries/study/TissueDistributionSummaryCalendarYr.query.xml +++ b/onprc_ehr/resources/queries/study/TissueDistributionSummaryCalendarYr.query.xml @@ -2,7 +2,7 @@ - Tissue Distribution Summary + Tissue Distribution Summary By Calendar Year Total Samples diff --git a/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr.query.xml b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr.query.xml new file mode 100644 index 000000000..db599ded7 --- /dev/null +++ b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr.query.xml @@ -0,0 +1,31 @@ + + + +
+ Tissue Distribution Summary By Animal ID Per Calendar Year + + + Total Samples + /query/executeQuery.view? + schemaName=study& + query.queryName=Tissue Distributions& + query.calendarYear~eq=${calendarYear}& + query.id~eq=${id}& + query.QCState/Label~in=Completed;Request: Pending& + + + + Distinct Animal IDs + /query/executeQuery.view? + schemaName=study& + query.queryName=Tissue Distributions& + query.calendarYear~eq=${calendarYear}& + query.id~eq=${id}& + query.QCState/Label~in=Completed;Request: Pending& + + + +
+
+
+ \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr.sql b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr.sql new file mode 100644 index 000000000..e834b541b --- /dev/null +++ b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr.sql @@ -0,0 +1,15 @@ +-- Added: 1-2-2018 R.Blasa +SELECT + calendarYear, + t.id, +-- t.recipient.affiliation, +-- t.requestCategory, + count(t.Id) as totalSamples, + count(distinct t.Id) as distinctAnimals, + count(distinct t.recipient) as distinctRecipients + +FROM study.tissueDistributions t +Where t.taskid is not null + And t.QCState.Label in ('Request: Pending','Completed') + +GROUP BY calendarYear, t.id \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr/.qview.xml b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr/.qview.xml new file mode 100644 index 000000000..4f925f9e0 --- /dev/null +++ b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDCalendarYr/.qview.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr.query.xml b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr.query.xml new file mode 100644 index 000000000..fb0a59734 --- /dev/null +++ b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr.query.xml @@ -0,0 +1,31 @@ + + + + + Tissue Distribution Summary By Animal ID Per Fiscal Year + + + Total Samples + /query/executeQuery.view? + schemaName=study& + query.queryName=Tissue Distributions& + query.fiscalYear~eq=${fiscalYear}& + query.id~eq=${id}& + query.QCState/Label~in=Completed;Request: Pending& + + + + Distinct Animal IDs + /query/executeQuery.view? + schemaName=study& + query.queryName=Tissue Distributions& + query.fiscalYear~eq=${fiscalYear}& + query.id~eq=${id}& + query.QCState/Label~in=Completed;Request: Pending& + + + +
+
+
+
\ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr.sql b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr.sql new file mode 100644 index 000000000..875e9381e --- /dev/null +++ b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr.sql @@ -0,0 +1,13 @@ +-- Added: 1-2-2018 R.Blasa +SELECT + fiscalYear, + t.id, + count(t.Id) as totalSamples, + count(distinct t.Id) as distinctAnimals, + count(distinct t.recipient) as distinctRecipients + +FROM study.tissueDistributions t +Where t.taskid is not null + And t.QCState.Label in ('Request: Pending','Completed') + +GROUP BY fiscalYear, t.id \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr/.qview.xml b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr/.qview.xml new file mode 100644 index 000000000..85a4caabd --- /dev/null +++ b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyAnimalIDFiscalYr/.qview.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/TissueDistributionSummarybyRecipientCalendarYr.query.xml b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyRecipientCalendarYr.query.xml index 518ec01a4..34ea7529c 100644 --- a/onprc_ehr/resources/queries/study/TissueDistributionSummarybyRecipientCalendarYr.query.xml +++ b/onprc_ehr/resources/queries/study/TissueDistributionSummarybyRecipientCalendarYr.query.xml @@ -2,7 +2,7 @@ - Tissue Distribution Summary By Recipient + Tissue Distribution Summary By Recipient By Calendar Year Total Samples diff --git a/onprc_ehr/resources/queries/study/demographicsAssignedVet.sql b/onprc_ehr/resources/queries/study/demographicsAssignedVet.sql index 8d4cc1842..61727ec5c 100644 --- a/onprc_ehr/resources/queries/study/demographicsAssignedVet.sql +++ b/onprc_ehr/resources/queries/study/demographicsAssignedVet.sql @@ -2,34 +2,24 @@ study.demographicsAssignedVet * Returns one or more assigned vets per animal ID -* Note to future self: don't be tempted to add more fields to this view. It will likely - result in additional rows per animal as they won't be distinct. - +* Note to future self: be very careful when adding more fields to this view. It can easily + result in additional rows per animal if they're distinct. */ --- Step 1: Find the minimum matchedRule for each ID -WITH MinMatchedRules AS ( - SELECT - VAF2.Id, - MIN(VAF2.matchedRule) AS MinRule - FROM - vetAssignment_Filter AS VAF2 - GROUP BY - VAF2.Id +SELECT + f.Id, + f.AssignedVet, + f.AssignmentType, + GROUP_CONCAT( + CASE WHEN f.matchedRule = 0 THEN f.ActiveMasterProblems ELSE NULL END, + ', ' + ) AS MasterProblems, + f.Area, + f.Room +FROM vetAssignment_filter f +WHERE f.matchedRule = ( + SELECT min(matchedRule) + FROM vetAssignment_filter sub + WHERE sub.Id = f.Id ) - --- Step 2: Join the original table with the filtered minimum matched rules -SELECT DISTINCT - VAF1.Id, - VAF1.AssignedVet, - VAF1.AssignmentType, - VAF1.Room, - VAF1.Area, - VAF1.Species - -FROM - vetAssignment_Filter AS VAF1 - INNER JOIN - MinMatchedRules AS MMR - ON VAF1.Id = MMR.Id - AND VAF1.matchedRule = MMR.MinRule \ No newline at end of file +GROUP BY f.Id, f.AssignedVet, f.AssignmentType, f.Area, f.Room \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/demographicsAssignedVet/.qview.xml b/onprc_ehr/resources/queries/study/demographicsAssignedVet/.qview.xml index 5a5a03550..9a4beb10c 100644 --- a/onprc_ehr/resources/queries/study/demographicsAssignedVet/.qview.xml +++ b/onprc_ehr/resources/queries/study/demographicsAssignedVet/.qview.xml @@ -4,11 +4,9 @@ - - - - - + + + diff --git a/onprc_ehr/resources/queries/study/demographicsAssignedVet/NHPsWithoutAnAssignedVet.qview.xml b/onprc_ehr/resources/queries/study/demographicsAssignedVet/NHPsWithoutAnAssignedVet.qview.xml index bb6014336..dc34659b9 100644 --- a/onprc_ehr/resources/queries/study/demographicsAssignedVet/NHPsWithoutAnAssignedVet.qview.xml +++ b/onprc_ehr/resources/queries/study/demographicsAssignedVet/NHPsWithoutAnAssignedVet.qview.xml @@ -4,11 +4,9 @@ - - - - - + + + diff --git a/onprc_ehr/resources/queries/study/demographicsOffspringBSU.query.xml b/onprc_ehr/resources/queries/study/demographicsOffspringBSU.query.xml index 7404ad7f6..cb64f6f1d 100644 --- a/onprc_ehr/resources/queries/study/demographicsOffspringBSU.query.xml +++ b/onprc_ehr/resources/queries/study/demographicsOffspringBSU.query.xml @@ -43,6 +43,14 @@ Foster Dam + + Surrogate Dam + + study + animal + id + + Sire diff --git a/onprc_ehr/resources/queries/study/demographicsOffspringBSU.sql b/onprc_ehr/resources/queries/study/demographicsOffspringBSU.sql index 26a72138b..47fe27b8d 100644 --- a/onprc_ehr/resources/queries/study/demographicsOffspringBSU.sql +++ b/onprc_ehr/resources/queries/study/demographicsOffspringBSU.sql @@ -17,6 +17,7 @@ d2.status, d2.geneticdam, d2.observeddam, d2.fosterMom, +d2.surrogateMom, d2.sire, d2.sireType, d.qcstate @@ -25,7 +26,7 @@ FROM study.Demographics d INNER JOIN study.demographicsParentsBSU d2 - ON ((d2.sire = d.id OR d2.geneticdam = d.id OR d2.fostermom = d.id OR d2.observeddam = d.id) AND d.id != d2.id) + ON ((d2.sire = d.id OR d2.geneticdam = d.id OR d2.fosterMom = d.id OR d2.observeddam = d.id) AND d.id != d2.id) diff --git a/onprc_ehr/resources/queries/study/demographicsOffspringBSU/.qview.xml b/onprc_ehr/resources/queries/study/demographicsOffspringBSU/.qview.xml index 4a4679a82..fd9958bee 100644 --- a/onprc_ehr/resources/queries/study/demographicsOffspringBSU/.qview.xml +++ b/onprc_ehr/resources/queries/study/demographicsOffspringBSU/.qview.xml @@ -15,6 +15,7 @@ + diff --git a/onprc_ehr/resources/queries/study/demographicsParents/.qview.xml b/onprc_ehr/resources/queries/study/demographicsParents/.qview.xml index 2ab5905b4..01e76b9af 100644 --- a/onprc_ehr/resources/queries/study/demographicsParents/.qview.xml +++ b/onprc_ehr/resources/queries/study/demographicsParents/.qview.xml @@ -6,6 +6,7 @@ + diff --git a/onprc_ehr/resources/queries/study/demographicsParentsBSU.query.xml b/onprc_ehr/resources/queries/study/demographicsParentsBSU.query.xml index 5790dc400..e947589e1 100644 --- a/onprc_ehr/resources/queries/study/demographicsParentsBSU.query.xml +++ b/onprc_ehr/resources/queries/study/demographicsParentsBSU.query.xml @@ -48,6 +48,14 @@ id + + Surrogate Dam + + study + animal + id + + Number of Parents Known diff --git a/onprc_ehr/resources/queries/study/demographicsParentsBSU.sql b/onprc_ehr/resources/queries/study/demographicsParentsBSU.sql index 76f64855f..66657396f 100644 --- a/onprc_ehr/resources/queries/study/demographicsParentsBSU.sql +++ b/onprc_ehr/resources/queries/study/demographicsParentsBSU.sql @@ -39,12 +39,23 @@ SELECT ELSE null END as sireType, - p3.parent as fosterMom, - p3.method as fosterType, - (CASE WHEN p3.parent IS NOT NULL THEN 1 ELSE 0 END + - CASE WHEN coalesce(p2.parent, b.dam) IS NOT NULL THEN 1 ELSE 0 END + - CASE WHEN coalesce(p1.parent, b.sire) IS NOT NULL THEN 1 ELSE 0 END) as numParents + coalesce(p3.parent, '') as fosterMom, + CASE + WHEN p3.parent IS NOT NULL THEN p3.method + ELSE null + END as fosterType, + + coalesce(p4.parent, '') as surrogateMom, + CASE + WHEN p4.parent IS NOT NULL THEN p4.method + ELSE null + END as surrogateType, + + (CASE WHEN p4.parent IS NOT NULL THEN 1 ELSE 0 END + + CASE WHEN p3.parent IS NOT NULL THEN 1 ELSE 0 END + + CASE WHEN coalesce(p2.parent, b.dam) IS NOT NULL THEN 1 ELSE 0 END + + CASE WHEN coalesce(p1.parent, b.sire) IS NOT NULL THEN 1 ELSE 0 END) as numParents FROM study.demographics d @@ -68,5 +79,12 @@ LEFT JOIN ( WHERE p3.relationship = 'Foster Dam' AND p3.enddate IS NULL GROUP BY p3.Id ) p3 ON (d.Id = p3.id) + +LEFT JOIN ( + select p4.id, min(p4.method) as method, max(p4.parent) as parent + FROM study.parentage p4 + WHERE p4.relationship = 'Surrogate Dam' AND p4.enddate IS NULL + GROUP BY p4.Id +) p4 ON (d.Id = p4.id) LEFT JOIN study.birth b ON (b.id = d.id) diff --git a/onprc_ehr/resources/queries/study/flags.query.xml b/onprc_ehr/resources/queries/study/flags.query.xml index e1e38b743..6c129e173 100644 --- a/onprc_ehr/resources/queries/study/flags.query.xml +++ b/onprc_ehr/resources/queries/study/flags.query.xml @@ -11,12 +11,12 @@ Date Added - Date + DateTime Date Removed false - Date + DateTime true diff --git a/onprc_ehr/resources/queries/study/parentageSummary.query.xml b/onprc_ehr/resources/queries/study/parentageSummary.query.xml index 1efefbcd2..8ebcede84 100644 --- a/onprc_ehr/resources/queries/study/parentageSummary.query.xml +++ b/onprc_ehr/resources/queries/study/parentageSummary.query.xml @@ -4,6 +4,12 @@
Parentage Summary + + Id + + + Date + Parent @@ -18,6 +24,12 @@ Method + + Comments + + + Data Source +
diff --git a/onprc_ehr/resources/queries/study/parentageSummary.sql b/onprc_ehr/resources/queries/study/parentageSummary.sql index d410bee51..a457c8a91 100644 --- a/onprc_ehr/resources/queries/study/parentageSummary.sql +++ b/onprc_ehr/resources/queries/study/parentageSummary.sql @@ -18,10 +18,14 @@ SELECT p.date, p.parent, p.relationship, - p.method + p.method, + p.remark, + 'Parentage' as source FROM study.parentage p WHERE p.qcstate.publicdata = true and p.enddate is null +And p.date in (select max(t.date) from study.parentage t where p.Id = t.Id And p.parent = t.parent +And p.relationship =t.relationship And p.method = t.method And t.enddate is null and p.enddate is null and t.qcstate.publicdata = true) UNION @@ -30,20 +34,23 @@ SELECT b.date, b.dam, 'Dam' as relationship, - 'Observed' as method + 'Observed' as method, + null as remark, + 'Birth' as source FROM study.birth b WHERE b.dam is not null and b.qcstate.publicdata = true -And 'dam' not in (select k.relationship from study.parentage k where k.Id = b.Id and k.enddate is null) + UNION SELECT a.Id, - a.date, + a.date, a.sire, 'Sire' as relationship, - 'Observed' as method + 'Observed' as method, + null as remark, + 'Birth' as source FROM study.birth a WHERE a.sire is not null and a.qcstate.publicdata = true - And 'sire' not in (select k.relationship from study.parentage k where k.Id = a.Id and k.enddate is null) \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/parentageSummary/.qview.xml b/onprc_ehr/resources/queries/study/parentageSummary/.qview.xml new file mode 100644 index 000000000..e5dbb867c --- /dev/null +++ b/onprc_ehr/resources/queries/study/parentageSummary/.qview.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/onprc_ehr/resources/queries/study/parentageSummary/Parentage With Dates.qview.xml b/onprc_ehr/resources/queries/study/parentageSummary/Parentage With Dates.qview.xml new file mode 100644 index 000000000..3393258cd --- /dev/null +++ b/onprc_ehr/resources/queries/study/parentageSummary/Parentage With Dates.qview.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/onprc_ehr/resources/schemas/dbscripts/sqlserver/onprc_ehr-25.003-25.004.sql b/onprc_ehr/resources/schemas/dbscripts/sqlserver/onprc_ehr-25.003-25.004.sql new file mode 100644 index 000000000..ac8027b7d --- /dev/null +++ b/onprc_ehr/resources/schemas/dbscripts/sqlserver/onprc_ehr-25.003-25.004.sql @@ -0,0 +1,141 @@ + +CREATE TABLE onprc_ehr.RequirementName_Convert( + searchid integer IDENTITY(100,1) NOT NULL, + PreviousDesignation varchar(255) NULL, + afterName varchar(255) NULL, + FileName varchar(1000) NULL + ) ON [PRIMARY] + GO + + +/* +** +** Created by Date Comment +** +** +** Blasa 1/6/2026 Convert Compliance Requirement Names to its new predefined names. +*/ + + +CREATE Procedure onprc_ehr.sp_Compliance_requirementname_Update_Process + + + + +AS + +DECLARE + + @SearchKey Int, + @TempsearchKey Int, + @Code varchar(500) +Begin + + + + ---Initial Values + set @TempSearchkey = 0 + set @Searchkey = 0 + + + +select top 1 @Searchkey= searchid from onprc_ehr.requirementname_Convert +order by searchid + + +While @TempSearchKey < @SearchKey +BEGIN + +select top 1 @Code=PreviousDesignation from onprc_ehr.requirementname_Convert + Where searchid = @Searchkey + + If @@Error <> 0 + GoTo Err_Proc + + ------Process Requirement Names + +Update ss +set ss.RequirementName = '' + trim(jj.aftername) + ' ' + trim(jj.filename) + '' + + from ehr_Compliancedb.Requirements ss, onprc_ehr.requirementname_Convert jj where ss.RequirementName like '' + trim(@code) + '%' + And jj.PreviousDesignation like '' + trim(@code) + '%' + + If @@Error <> 0 + GoTo Err_Proc + +------Process Completion Dates + +Update ss +set ss.RequirementName = '' + trim(jj.aftername) + ' ' + trim(jj.filename) + '' + + from ehr_Compliancedb.CompletionDates ss, onprc_ehr.requirementname_Convert jj where ss.RequirementName like '' + trim(@code) + '%' + And jj.PreviousDesignation like '' + trim(@code) + '%' + + If @@Error <> 0 + GoTo Err_Proc + +------Process Requirements per Employees + +Update ss +set ss.RequirementName = '' + trim(jj.aftername) + ' ' + trim(jj.filename) + '' + + from ehr_Compliancedb.RequirementsPerEmployee ss, onprc_ehr.requirementname_Convert jj where ss.RequirementName like '' + trim(@code) + '%' + And jj.PreviousDesignation like '' + trim(@code) + '%' + + If @@Error <> 0 + GoTo Err_Proc + +-----Process Requirements per Categories + +Update ss +set ss.RequirementName = '' + trim(jj.aftername) + ' ' + trim(jj.filename) + '' + + from ehr_Compliancedb.RequirementsPerCategory ss, onprc_ehr.requirementname_Convert jj where ss.RequirementName like '' + trim(@code) + '%' + And jj.PreviousDesignation like '' + trim(@code) + '%' + + If @@Error <> 0 + GoTo Err_Proc + +-----Process Employee Requirements Exemptions + +Update ss +set ss.RequirementName = '' + trim(jj.aftername) + ' ' + trim(jj.filename) + '' + + from ehr_Compliancedb.EmployeeRequirementExemptions ss, onprc_ehr.requirementname_Convert jj where ss.RequirementName like '' + trim(@code) + '%' + And jj.PreviousDesignation like '' + trim(@code) + '%' + + If @@Error <> 0 + GoTo Err_Proc + + +----- Process the next data record + +Set @TempSearchkey = @SearchKey + + +select top 1 @Searchkey= searchid from onprc_ehr.requirementname_Convert +Where searchid > @TempSearchkey +order by searchid + + If @@Error <> 0 + GoTo Err_Proc + + +END ---(While) + + + +RETURN 0 + + + Err_Proc: + + + RETURN 1 + + +END + +GO + + diff --git a/onprc_ehr/resources/schemas/onprc_ehr.xml b/onprc_ehr/resources/schemas/onprc_ehr.xml index 875814163..298c65edc 100644 --- a/onprc_ehr/resources/schemas/onprc_ehr.xml +++ b/onprc_ehr/resources/schemas/onprc_ehr.xml @@ -1471,4 +1471,13 @@ + + + + + + + +
+ diff --git a/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js b/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js index d6f8da6ac..1532b529a 100644 --- a/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js +++ b/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js @@ -483,8 +483,8 @@ exports.init = function(EHR){ EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.INIT, 'study', 'flags', function(event, helper){ helper.setScriptOptions({ allowFutureDates: true, - removeTimeFromDate: true, - removeTimeFromEndDate: true + removeTimeFromDate: false, + removeTimeFromEndDate: false }); EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'flags', EHR.Server.TriggerManager.Events.AFTER_INSERT); @@ -1053,7 +1053,7 @@ exports.init = function(EHR){ } //Added by Kollil, 8/1/24 - /* User can bypass the enddate for these two medications, as per ticket #11016 + /* User can bypass the enddate for the following meddications, as per ticket #11016 Validation code on the Prime side to bypass the following two medications without entering the end dates. 1. E-85760 - Medroxyprogesterone injectable (150mg/ml) 2. E-Y7735 - Diet - Weekly Multivitamin @@ -1061,11 +1061,13 @@ exports.init = function(EHR){ Added these two Diets to the list by Kollil on 4/15/25. Refer to tkt #12363 3. E-X0500 - Diet, L-Phyto (Low-phytoestrogen) 4. E-Y9750 - Diet, 5047 High Protein, Jumbo + + Added Diet to the list by Kollil on 5/14/25. Refer to tkt #12506 + 5. E-X1380 - Diet Daily (Non-standard), 5LOP (TAD) */ - if (row.code != 'E-85760' && row.code != 'E-Y7735' && row.code != 'E-X0500' && row.code != 'E-Y9750'){ - if (!row.enddate) { - EHR.Server.Utils.addError(scriptErrors, 'enddate', 'Must enter enddate', 'WARN'); - } + if (row.code != 'E-85760' && row.code != 'E-Y7735' && row.code != 'E-X0500' && + row.code != 'E-Y9750' && row.code != 'E-X1380' && !row.enddate) { + EHR.Server.Utils.addError(scriptErrors, 'enddate', 'Must enter enddate', 'WARN'); } //Added by Kollil, 9/15/25 diff --git a/onprc_ehr/resources/web/onprc_ehr/model/sources/Flag_settings.js b/onprc_ehr/resources/web/onprc_ehr/model/sources/Flag_settings.js new file mode 100644 index 000000000..57d9a9d12 --- /dev/null +++ b/onprc_ehr/resources/web/onprc_ehr/model/sources/Flag_settings.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014 LabKey Corporation + * + * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 + */ +EHR.model.DataModelManager.registerMetadata('Flag_Settings', { + allQueries: { + + }, + byQuery: { + 'study.flags': { + date: { + xtype: 'xdatetime', + extFormat: LABKEY.extDefaultDateTimeFormat, + editorConfig: { + dateFormat: LABKEY.extDefaultDateFormat, + timeFormat: 'H:i' + } + + }, + enddate: { + xtype: 'xdatetime', + extFormat: LABKEY.extDefaultDateTimeFormat, + editorConfig: { + dateFormat: LABKEY.extDefaultDateFormat, + timeFormat: 'H:i' + } + + } + + } + } +}); \ No newline at end of file diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/ONPRC_EHRModule.java b/onprc_ehr/src/org/labkey/onprc_ehr/ONPRC_EHRModule.java index a8164a775..d18c157d4 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/ONPRC_EHRModule.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/ONPRC_EHRModule.java @@ -124,7 +124,7 @@ public String getName() @Override public @Nullable Double getSchemaVersion() { - return 25.003; + return 25.004; } @Override @@ -498,7 +498,14 @@ public String toString() // Added 1-2-2018 R.Blasa EHRService.get().registerReportLink(EHRService.REPORT_LINK_TYPE.moreReports, "View Tissue Distribution Summary, By Recipient(Calendar Year)", this, DetailsURL.fromString("/query/executeQuery.view?schemaName=study&query.queryName=tissueDistributionSummaryByRecipientCalendarYr"), "Pathology"); - //Added: 12-7-2017 R.Blasa + // Added 1-7-2026 R.Blasa + EHRService.get().registerReportLink(EHRService.REPORT_LINK_TYPE.moreReports, "View Tissue Distribution Summary, By Animal ID(Calendar Year)", this, DetailsURL.fromString("/query/executeQuery.view?schemaName=study&query.queryName=tissueDistributionSummaryByAnimalIDCalendarYr"), "Pathology"); + + // Added 1-7-2026 R.Blasa + EHRService.get().registerReportLink(EHRService.REPORT_LINK_TYPE.moreReports, "View Tissue Distribution Summary, By Animal ID(Fiscal Year)", this, DetailsURL.fromString("/query/executeQuery.view?schemaName=study&query.queryName=tissueDistributionSummaryByAnimalIDFiscalYr"), "Pathology"); + + + //Added: 12-7-2017 R.Blasa // EHRService.get().registerReportLink(EHRService.REPORT_LINK_TYPE.moreReports, "Animal Census on a Given Date Range", this, DetailsURL.fromString("/onprc_ehr/CensusGivenDateRange.view"), "Colony Management"); // Added: 2-2-2021 R.Blasa diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/BloodDrawFormType.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/BloodDrawFormType.java index c73c835b1..edbe49d39 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/BloodDrawFormType.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/BloodDrawFormType.java @@ -25,6 +25,10 @@ import org.labkey.api.ehr.dataentry.WeightFormSection; import org.labkey.api.module.Module; import org.labkey.api.view.template.ClientDependency; +import org.labkey.security.xml.GroupEnumType; +import org.labkey.api.security.GroupManager; +import org.labkey.api.security.Group; +import org.labkey.api.security.permissions.AdminPermission; import java.util.Arrays; import java.util.List; @@ -69,4 +73,15 @@ public Supplier getAddScheduledTreatmentWindowDependency() { return ClientDependency.supplierFromPath("ehr/window/AddScheduledTreatmentWindow.js"); } + //Added: 1-15-2026 R.Blasa + @Override + public boolean isVisible() + { + Group g = GroupManager.getGroup(getCtx().getContainer(), "Form Clinical Rounds SF", GroupEnumType.SITE); + if (g != null && getCtx().getUser().isInGroup(g.getUserId()) && !getCtx().getContainer().hasPermission(getCtx().getUser(), AdminPermission.class)) + { + return false; + } + return super.isVisible(); + } } diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/ClinicalRoundsFormType.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/ClinicalRoundsFormType.java index b0040122c..ab5d20c96 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/ClinicalRoundsFormType.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/ClinicalRoundsFormType.java @@ -77,12 +77,4 @@ public ClinicalRoundsFormType(DataEntryFormContext ctx, Module owner) } - @Override - protected boolean canInsert() - { - if (!getCtx().getContainer().hasPermission(getCtx().getUser(), EHRClinicalEntryPermission.class)) - return false; - - return super.canInsert(); - } } diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/FlagsFormType.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/FlagsFormType.java index 43c3631c4..362f42144 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/FlagsFormType.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/FlagsFormType.java @@ -26,6 +26,7 @@ import org.labkey.api.security.GroupManager; import org.labkey.api.security.permissions.AdminPermission; import org.labkey.api.security.permissions.Permission; +import org.labkey.api.view.template.ClientDependency; import org.labkey.security.xml.GroupEnumType; import java.util.ArrayList; @@ -49,6 +50,12 @@ public FlagsFormType(DataEntryFormContext ctx, Module owner) new SimpleGridPanel("study", "flags", "Flags") )); + addClientDependency(ClientDependency.supplierFromPath("onprc_ehr/model/sources/Flag_settings.js")); + + for (FormSection s : getFormSections()) + { + s.addConfigSource("Flag_Settings"); + } } diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/MedSignoffFormType.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/MedSignoffFormType.java index 86312e8a4..4a221596b 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/MedSignoffFormType.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/MedSignoffFormType.java @@ -72,11 +72,11 @@ protected boolean canInsert() return super.canInsert(); } - //Modified: 12-5-2019 R.Blasa + //Modified: 12-11-2025 R.Blasa @Override public boolean isVisible() { - Group g = GroupManager.getGroup(getCtx().getContainer(), "ASB Support", GroupEnumType.SITE); + Group g = GroupManager.getGroup(getCtx().getContainer(), "Clinical Entry", GroupEnumType.SITE); if (g != null && getCtx().getUser().isInGroup(g.getUserId()) && !getCtx().getContainer().hasPermission(getCtx().getUser(), AdminPermission.class)) { return false; diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/NHPTrainingFormType.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/NHPTrainingFormType.java index 54bd16e60..8faf1cba8 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/NHPTrainingFormType.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/NHPTrainingFormType.java @@ -21,7 +21,11 @@ import org.labkey.api.ehr.dataentry.TaskFormSection; import org.labkey.api.ehr.security.EHRBehaviorEntryPermission; import org.labkey.api.module.Module; +import org.labkey.api.security.Group; +import org.labkey.api.security.GroupManager; +import org.labkey.api.security.permissions.AdminPermission; import org.labkey.api.view.template.ClientDependency; +import org.labkey.security.xml.GroupEnumType; import java.util.Arrays; diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/PairingFormType.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/PairingFormType.java index 19b877428..abf1da752 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/PairingFormType.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/PairingFormType.java @@ -66,19 +66,7 @@ public PairingFormType(DataEntryFormContext ctx, Module owner) addClientDependency(ClientDependency.supplierFromPath("/onprc_ehr/form/field/PairedAdultsEntryField.js")); - - - - - } - @Override - protected boolean canInsert() - { - if (!getCtx().getContainer().hasPermission(getCtx().getUser(), EHRBehaviorEntryPermission.class)) - return false; - return super.canInsert(); - } } diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/notification/AdminNotifications.java b/onprc_ehr/src/org/labkey/onprc_ehr/notification/AdminNotifications.java index 427f50039..d9fc7fd8e 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/notification/AdminNotifications.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/notification/AdminNotifications.java @@ -101,19 +101,18 @@ private void MedsEndDateAlert(Container c, User u, final StringBuilder msg, fina TableSelector ts = new TableSelector(ti, null, new Sort("date")); long count = ts.getRowCount(); if (count == 0) { - //msg.append("There are no meds ordered except E-85760 (Medroxyprogesterone injectable 150mg/ml) and E-Y7735 (Diet - Weekly Multivitamin) with missing end dates!
"); - msg.append("No medication orders found with missing end date except the following approved list:" + + msg.append("No treatment orders found with missing end date except the following approved list:" + "
1. E-85760 (Medroxyprogesterone injectable 150mg/ml) " + "
2. E-Y7735 (Diet - Weekly Multivitamin)" + "
3. E-X0500 (Diet, L-Phyto (Low-phytoestrogen)) " + - "
4. E-Y9750 (Diet, 5047 High Protein, Jumbo)

"); + "
4. E-Y9750 (Diet, 5047 High Protein, Jumbo) " + + "
5. E-X1380 (Diet Daily (Non-standard), 5LOP (TAD))
"); } else if (count > 0) { //Display the report link on the notification page - msg.append("
Meds with missing end date:

"); - msg.append("" + count + " meds found with missing end dates:"); - msg.append("

Click here to view the meds/diets

\n"); + msg.append("
" + count + " treatment order(s) found with missing end dates

"); + msg.append("

Click here to view the treatments

\n"); msg.append("
"); //Display the report in the email diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/notification/BehaviorNotification.java b/onprc_ehr/src/org/labkey/onprc_ehr/notification/BehaviorNotification.java index 03f4a35f8..e2829e445 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/notification/BehaviorNotification.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/notification/BehaviorNotification.java @@ -17,10 +17,14 @@ import org.apache.commons.lang3.time.DateUtils; import org.json.JSONObject; +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.Results; +import org.labkey.api.data.ResultsImpl; import org.labkey.api.data.SQLFragment; +import org.labkey.api.data.Selector; import org.labkey.api.data.SimpleFilter; import org.labkey.api.data.Sort; import org.labkey.api.data.SqlSelector; @@ -35,14 +39,18 @@ import org.labkey.api.security.User; import org.labkey.api.util.PageFlowUtil; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; /** * User: bimber @@ -107,6 +115,17 @@ public String getMessageBodyHTML(Container c, User u) NHPTraining_BehaviorAlert(c, u , msg); AlopeciaScoreAlert(c, u , msg); dcmNotesAlert(c, u , msg); + //Added by Kollil, Nov 2025 + //Refer to tkt # 13618 + assignmentsCreatedInPast1Day(c,u,msg); + assignmentsReleasedInPast1Day(c,u,msg); + assignmentsStartingNext1to14Days(c,u,msg); + assignmentsStartedPast1to7Days(c,u,msg); + + //Added by Kollil, Jan 2026 + //Refer to tkt # 14056 + activeAssignmentsUnderTheAge(c,u,msg); + assignmentPoolUnderTheAge(c,u,msg); notesEndingToday(c, u, msg, Arrays.asList("BSU Notes"), null); saveValues(c, toSave); @@ -114,6 +133,257 @@ public String getMessageBodyHTML(Container c, User u) return msg.toString(); } + /* Added by Kollil, Jan 2026 + Refer to tkt # 14056 + The grid should include: + - Animals under the age of 2.5 with an active assignment. Exclude the U42 and U42E colony maintenance assignments, I believe the center projects for these are 0492-02 and 0492-03. + - Animals under the age of 2.5 with an "Assignment pool" note in PRIMe (under general>notes) + - 2/11/26 - change the age animals under 3 years old + */ + private void activeAssignmentsUnderTheAge(final Container c, User u, final StringBuilder msg) + { + TableInfo ti = getStudySchema(c, u).getTable("AssignmentsUnderTheAge"); + + TableSelector ts = new TableSelector(ti, null, new Sort("Id")); + long total = ts.getRowCount(); + + if (total > 0) + { + msg.append("Animals under the age of 3 with an active assignment excluding the U42 & U42E assignments:

"); + msg.append( total + " entries found. "); + msg.append("Click here to view them\n"); + msg.append("


\n\n"); + } + else { + msg.append("WARNING: No animals under the age of 3 with an active assignment!

\n"); + } + } + + private void assignmentPoolUnderTheAge(final Container c, User u, final StringBuilder msg) + { + TableInfo ti = getStudySchema(c, u).getTable("AssignmentPoolUnderTheAge"); + + TableSelector ts = new TableSelector(ti, null, new Sort("Id")); + long total = ts.getRowCount(); + + if (total > 0) + { + msg.append("Animals under the age of 3 with \"Assignment pool\" notes:

"); + msg.append( total + " entries found. "); + msg.append("Click here to view them\n"); + msg.append("


\n\n"); + } + else { + msg.append("WARNING: No animals under the age of 3 with an \"Assignment pool\" notes!

\n"); + } + } + + /* Added by Kollil Nov, 2025 + Priority 4: Add links to grids 3 and 4 in daily Behavior Alerts email (do not need to display full grid in email) + - for grid 3 - "There are __ assignments starting in the Next 1-14 days" with a link + Refer to tkt # 13618 + */ + private void assignmentsStartingNext1to14Days(final Container c, User u, final StringBuilder msg) + { + TableInfo ti = getStudySchema(c, u).getTable("AssignmentsStartingNext1to14Days"); + + TableSelector ts = new TableSelector(ti, null, new Sort("Id")); + long total = ts.getRowCount(); + + if (total > 0) + { + msg.append("Assignments starting in the next 1-14 days:

"); + msg.append( total + " entries found. "); + msg.append("Click here to view them\n"); + msg.append("


\n\n"); + } + else { + msg.append("WARNING: No assignments starting in the next 1-14 days!

\n"); + } + } + + /* Added by Kollil Nov, 2025 + Priority 4: Add links to grids 3 and 4 in daily Behavior Alerts email (do not need to display full grid in email) + - for grid 4 - "There were __ assignments started in the past 1-7 days" with a link + Refer to tkt # 13618 + */ + private void assignmentsStartedPast1to7Days(final Container c, User u, final StringBuilder msg) + { + TableInfo ti = getStudySchema(c, u).getTable("AssignmentsStartedPast1to7Days"); + + TableSelector ts = new TableSelector(ti, null, new Sort("Id")); + long total = ts.getRowCount(); + + if (total > 0) + { + msg.append("Assignments started in the past 1-7 days:

"); + msg.append( total + " entries found. "); + msg.append("Click here to view them\n"); + msg.append("


\n\n"); + } + else { + msg.append("WARNING: No assignments started in the past 1-7 days!

\n"); + } + } + + /* Added by Kollil Nov, 2025 + List of assignment records created by R&L in past 24hrs (this is the most important grid) + a. Replaces current grid “Assignments Modified in Past 1 Day” which captures any modifications to records in the last 24hrs + b. To clarify, not the same as records with the “assign date” within the past day + c. Include Day Leases + Refer to tkt # 13618 + */ + private void assignmentsCreatedInPast1Day(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; + } + //assignments query + TableInfo ti = QueryService.get().getUserSchema(u, c, "study").getTable("AssignmentsCreatedInPast1Day", ContainerFilter.Type.AllFolders.create(c, u)); + TableSelector ts = new TableSelector(ti, null, new Sort("Id")); + long count = ts.getRowCount(); + + //Get num of rows + if (count > 0) { + msg.append("Assignments created in the past 24hrs:

"); + msg.append( count + " entries found. "); + msg.append("Click here to view them in a separate window\n"); + msg.append("\n\n"); + + //Display the daily report in the email + Set columns = new HashSet<>(); + columns.add(FieldKey.fromString("Id")); + columns.add(FieldKey.fromString("Sex")); + columns.add(FieldKey.fromString("Room")); + columns.add(FieldKey.fromString("Cage")); + columns.add(FieldKey.fromString("project")); + columns.add(FieldKey.fromString("Protocol")); + columns.add(FieldKey.fromString("Title")); + columns.add(FieldKey.fromString("ProjectInvestigator")); + columns.add(FieldKey.fromString("AssignDate")); + columns.add(FieldKey.fromString("ReleaseDate")); + columns.add(FieldKey.fromString("ProjectedReleaseDate")); + columns.add(FieldKey.fromString("assignmentType")); + columns.add(FieldKey.fromString("assignCondition")); + columns.add(FieldKey.fromString("projectedReleaseCondition")); + columns.add(FieldKey.fromString("ConditionAtRelease")); + + final Map colMap = QueryService.get().getColumns(ti, columns); + TableSelector ts2 = new TableSelector(ti, colMap.values(), null, new Sort("Id")); + +// msg.append("


Assignments created in past 24hrs:

\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(""); + msg.append("\n"); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + }); + msg.append("
Id Sex Room Cage Project Protocol Title Project Investigator Assign Date Release Date Projected Release Date Assignment Type Assign Condition Projected Release Condition Condition At Release
" + PageFlowUtil.filter(rs.getString("Id")) + " " + PageFlowUtil.filter(rs.getString("Sex")) + "" + PageFlowUtil.filter(rs.getString("Room")) + "" + PageFlowUtil.filter(rs.getString("Cage")) + "" + PageFlowUtil.filter(rs.getString("project")) + "" + PageFlowUtil.filter(rs.getString("Protocol")) + "" + PageFlowUtil.filter(rs.getString("Title")) + "" + PageFlowUtil.filter(rs.getString("ProjectInvestigator")) + "" + PageFlowUtil.filter(rs.getString("AssignDate")) + "" + PageFlowUtil.filter(rs.getString("ReleaseDate")) + "" + PageFlowUtil.filter(rs.getString("ProjectedReleaseDate")) + "" + PageFlowUtil.filter(rs.getString("assignmentType")) + "" + PageFlowUtil.filter(rs.getString("assignCondition")) + "" + PageFlowUtil.filter(rs.getString("projectedReleaseCondition")) + "" + PageFlowUtil.filter(rs.getString("ConditionAtRelease")) + "


"); + } + else { + msg.append("WARNING: No assignments created in the past 24hrs!

\n"); + } + } + + /* Added by Kollil Nov, 2025 + Grid 2: List of records with new “Release date” added within the last 24hrs + a. Omit Day Leases + Refer to tkt # 13618 + */ + private void assignmentsReleasedInPast1Day(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; + } + + //assignments query + TableInfo ti = QueryService.get().getUserSchema(u, c, "study").getTable("AssignmentsReleasedInPast1Day", ContainerFilter.Type.AllFolders.create(c, u)); + TableSelector ts = new TableSelector(ti, null, new Sort("Id")); + long count = ts.getRowCount(); + + //Get num of rows + if (count > 0) { + msg.append("Assignments with new \"Release date\" added in the last 24hrs:

"); + msg.append( count + " entries found. "); + msg.append("Click here to view them in a separate window\n"); + msg.append("\n\n"); + + //Display the daily report in the email + Set columns = new HashSet<>(); + columns.add(FieldKey.fromString("Id")); + columns.add(FieldKey.fromString("Sex")); + columns.add(FieldKey.fromString("Room")); + columns.add(FieldKey.fromString("Cage")); + columns.add(FieldKey.fromString("project")); + columns.add(FieldKey.fromString("Protocol")); + columns.add(FieldKey.fromString("Title")); + columns.add(FieldKey.fromString("ProjectInvestigator")); + columns.add(FieldKey.fromString("AssignDate")); + columns.add(FieldKey.fromString("ReleaseDate")); + columns.add(FieldKey.fromString("ProjectedReleaseDate")); + columns.add(FieldKey.fromString("assignmentType")); + columns.add(FieldKey.fromString("assignCondition")); + columns.add(FieldKey.fromString("projectedReleaseCondition")); + columns.add(FieldKey.fromString("ConditionAtRelease")); + + final Map colMap = QueryService.get().getColumns(ti, columns); + TableSelector ts2 = new TableSelector(ti, colMap.values(), null, new Sort("Id")); + +// msg.append("


Assignments with new \"Release date\" added within the last 24hrs:

\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(""); + msg.append("\n"); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + msg.append(""); + }); + msg.append("
Id Sex Room Cage Project Protocol Title Project Investigator Assign Date Release Date Projected Release Date Assignment Type Assign Condition Projected Release Condition Condition At Release
" + PageFlowUtil.filter(rs.getString("Id")) + " " + PageFlowUtil.filter(rs.getString("Sex")) + "" + PageFlowUtil.filter(rs.getString("Room")) + "" + PageFlowUtil.filter(rs.getString("Cage")) + "" + PageFlowUtil.filter(rs.getString("project")) + "" + PageFlowUtil.filter(rs.getString("Protocol")) + "" + PageFlowUtil.filter(rs.getString("Title")) + "" + PageFlowUtil.filter(rs.getString("ProjectInvestigator")) + "" + PageFlowUtil.filter(rs.getString("AssignDate")) + "" + PageFlowUtil.filter(rs.getString("ReleaseDate")) + "" + PageFlowUtil.filter(rs.getString("ProjectedReleaseDate")) + "" + PageFlowUtil.filter(rs.getString("assignmentType")) + "" + PageFlowUtil.filter(rs.getString("assignCondition")) + "" + PageFlowUtil.filter(rs.getString("projectedReleaseCondition")) + "" + PageFlowUtil.filter(rs.getString("ConditionAtRelease")) + "


"); + } + else { + msg.append("WARNING: No assignments released in the past 24hrs!

\n"); + } + } /* Added by Kollil 08/22/2025 New alert/notification for when an animal receives an alopecia score of 4 or 5, but does not have an open behavioral case for alopecia. @@ -128,16 +398,15 @@ private void AlopeciaScoreAlert(final Container c, User u, final StringBuilder m msg.append("Animals with alopecia score of 4 or 5, but does not have an open behavioral case for alopecia:

"); if (total > 0) { - msg.append("There are " + total + " entries found. "); - msg.append("

Click here to view them

\n"); + msg.append( total + " entries found. "); + msg.append("Click here to view them\n"); msg.append("
\n\n"); } else { msg.append("WARNING: No animals found with alopecia score of 4 or 5, but does not have an open behavioral case for alopecia!

\n"); } - - } + } // Added by Kollil 11/04/2020 private void NHPTraining_BehaviorAlert(final Container c, User u, final StringBuilder msg) @@ -155,14 +424,13 @@ private void NHPTraining_BehaviorAlert(final Container c, User u, final StringBu if (total > 0) { msg.append("There are " + total + " entries found. "); - msg.append("

Click here to view them

\n"); + msg.append("Click here to view them\n"); msg.append("
\n\n"); } else { msg.append("WARNING: There are no NHP_Training entries where \"Training Result = In Progress\" for over 60 days!

\n"); } - } /* @@ -184,9 +452,9 @@ protected void dcmNotesAlert(final Container c, User u, final StringBuilder msg) long count = ts.getRowCount(); if (count > 0) { - msg.append("WARNING: There are " + count + " DCM action items.
\n"); - msg.append("

Click here to view them
\n\n"); - msg.append("



"); + msg.append("WARNING: There are " + count + " DCM action items.
\n"); + msg.append("Click here to view them
\n\n"); + msg.append("

"); } else { @@ -209,8 +477,8 @@ protected void dcmNotesAlert(final Container c, User u, final StringBuilder msg) msg.append("DCM Alerts:

"); if (count1 > 0) { msg.append("" + count1 + " DCM notes entries added yesterday where \"Category = Notes pertaining to DAR\".
\n"); - msg.append("

Click here to view them
\n\n"); - msg.append("



\n\n"); + msg.append("Click here to view them
\n\n"); + msg.append("

\n\n"); } else { @@ -228,8 +496,8 @@ New alert for DCM notes (category = notes pertaining to DAR) removed the previou if (count4 > 0) { msg.append("" + count4 + " DCM notes entries removed yesterday where \"Category = Notes pertaining to DAR\".
\n"); - msg.append("

Click here to view them
\n\n"); - msg.append("



\n\n"); + msg.append("Click here to view them
\n\n"); + msg.append("

\n\n"); } else { msg.append("WARNING: No DCM notes ended yesterday where \"Category = Notes pertaining to DAR\"!

"); @@ -243,8 +511,8 @@ New alert for DCM notes (category = notes pertaining to DAR) removed the previou if (count2 > 0) { msg.append("There are " + count2 + " flag(s) added yesterday.
\n"); - msg.append("

Click here to view them
\n\n"); - msg.append("


"); + msg.append("Click here to view them
\n\n"); + msg.append("
"); } else { @@ -258,8 +526,8 @@ New alert for DCM notes (category = notes pertaining to DAR) removed the previou long count3 = ts3.getRowCount(); if (count3 > 0) { msg.append("" + count3 + " flag(s) removed yesterday.
\n"); - msg.append("

Click here to view them
\n\n"); - msg.append("


"); + msg.append("Click here to view them
\n\n"); + msg.append("
"); } else { msg.append("WARNING: There are no flags removed yesterday!

"); 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 0a40e50fa..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 @@ -1551,7 +1615,7 @@ else if (rs.getString("ActiveClinicalTreatment") != null && rs.getString("Active protected void LongTermMedsAlert(final Container c, User u, final StringBuilder msg) { if (QueryService.get().getUserSchema(u, c, "onprc_ehr") == null) { - msg.append("Warning: The study schema has not been enabled in this folder, so the alert cannot run!


"); + msg.append("Warning: The onprc_ehr schema has not been enabled in this folder, so the alert cannot run!


"); return; } @@ -2333,6 +2397,33 @@ protected void duplicateFlags(Container c, User u, final StringBuilder msg) } } + /** + * Created by Kollil, 10/25 + * Get a list of tasks daily on a rolling 7 day window to review for QC. + * This will allow techs to see what new IDs were created by whom, and review for accuracy, + * housing history, group ids and flags. + * Refer tkt # 13504 + */ + protected void newBirthTasks(final Container c, User u, final StringBuilder msg) + { + if (QueryService.get().getUserSchema(u, c, "onprc_ehr") == null) { + msg.append("Warning: The onprc_ehr schema has not been enabled in this folder, so the alert cannot run!


"); + return; + } + + //Get birth tasks + TableInfo ti = QueryService.get().getUserSchema(u, c, "onprc_ehr").getTable("NewBirthTasks", ContainerFilter.Type.AllFolders.create(c, u)); + TableSelector ts = new TableSelector(ti, null, null); + long count = ts.getRowCount(); + + if (count > 0) { + msg.append("WARNING: There are " + count + " new birth(s) found in last 7 days.
"); + msg.append("

Click here to view them

\n"); + msg.append("
"); + } + + } + /** * Created by Kollil, 9/6/23 * Get the new animals found with the flag, "NHPR NOTE: BCG Vaccinated". 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); diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/notification/DataValidationNotification.java b/onprc_ehr/src/org/labkey/onprc_ehr/notification/DataValidationNotification.java index 79b34ea4c..11080a1de 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/notification/DataValidationNotification.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/notification/DataValidationNotification.java @@ -48,19 +48,19 @@ public String getEmailSubject(Container c) @Override public String getCronString() { - return "0 25 6 * * ?"; + return "0 50 6,15 * * ?"; } @Override public String getScheduleDescription() { - return "every day at 6:25AM"; + return "every day at 6:50AM and 3:50PM"; } @Override public String getDescription() { - return "The report is designed to identify potential problems with the EHR data. It is similar to Colony Alerts, except it is limited to alerts that indicate a true problem in the data itself."; + return "The report identifies potential problems with the EHR data. Although similar to Colony Alerts, it is limited to problems in the data itself."; } @Override @@ -112,11 +112,14 @@ public String getMessageBodyHTML(Container c, User u) birthRecordsNotMatchingHousing(c, u, msg); duplicateGroupMembership(c, u, msg); duplicateFlags(c, u, msg); + //Added by Kolli, Oct 2025 + //Tasks list alert for the new animal births, Refer to # 13504 + newBirthTasks(c, u, msg); //only send if there are alerts if (!msg.isEmpty()) { - msg.insert(0, "This email contains a series of automatic alerts designed to identify problems in the EHR data. It was run on: " + getDateFormat(c).format(now) + " at " + _timeFormat.format(now) + ".

"); + msg.insert(0, "This email contains a series of automatic alerts identifying problems in the EHR data. It was run on: " + getDateFormat(c).format(now) + " at " + _timeFormat.format(now) + ".

"); } return msg.toString(); diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/security/ONPRC_EHREnvironmentalPermission.java b/onprc_ehr/src/org/labkey/onprc_ehr/security/ONPRC_EHREnvironmentalPermission.java index 95ca1815e..0a909fed7 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/security/ONPRC_EHREnvironmentalPermission.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/security/ONPRC_EHREnvironmentalPermission.java @@ -24,6 +24,6 @@ public class ONPRC_EHREnvironmentalPermission extends AbstractPermission { public ONPRC_EHREnvironmentalPermission() { - super("ONPRC_EHREnvironmentalPermission", "This is the base permission used to control editing of the Envioenmental Assessment"); + super("ONPRC_EHREnvironmentalPermission", "This is the base permission used to control editing of the Environmental Assessment"); } } diff --git a/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java b/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java index e1313a66f..bdf812dd0 100644 --- a/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java +++ b/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java @@ -1073,7 +1073,6 @@ public void testExamEntry() throws Exception Assert.assertEquals("mg/kg", ordersGrid.getFieldValue(3, "dosage_units")); //note: amount calculation testing handled in surgery test - //blood draws waitAndClick(Ext4Helper.Locators.ext4Tab("Blood Draws")); Ext4GridRef bloodGrid = _helper.getExt4GridForFormSection("Blood Draws"); diff --git a/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_RestrictedIssueTest.java b/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_RestrictedIssueTest.java index 7e54dae2c..5d0abf4a0 100644 --- a/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_RestrictedIssueTest.java +++ b/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_RestrictedIssueTest.java @@ -1,5 +1,6 @@ package org.labkey.test.tests.onprc_ehr; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -11,7 +12,9 @@ import org.labkey.test.pages.issues.DetailsPage; import org.labkey.test.pages.issues.InsertPage; import org.labkey.test.pages.issues.UpdatePage; +import org.labkey.test.pages.search.SearchResultsPage; import org.labkey.test.util.IssuesHelper; +import org.labkey.test.util.SearchHelper; import org.labkey.test.util.SqlserverOnlyTest; import org.labkey.test.util.TestUser; @@ -265,4 +268,37 @@ private Locator getIssueLinkLocator(String issueID) { return Locator.tagWithAttributeContaining("a", "href", String.format("issues-details.view?issueId=%s", issueID)); } + + @Test + public void restrictedIssueSearchTest() + { + goToProjectHome(); + + // create a few issues in the restricted list + clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST)); + DetailsPage detailsPage = _issuesHelper.addIssue("Restricted issue search test #1", USER1.getUserDisplayName()); + final String ISSUE_1 = detailsPage.getIssueId(); + InsertPage insertPage = detailsPage.clickCreateNewIssue(); + insertPage.title().set("Restricted issue search test #2"); + insertPage.assignedTo().set(USER2.getUserDisplayName()); + detailsPage = insertPage.save(); + final String ISSUE_2 = detailsPage.getIssueId(); + + SearchHelper searchHelper = new SearchHelper(this); + SearchResultsPage resultsPage = searchHelper.searchFor("Restricted issue search test"); + + // verify that we can return links even if the user doesn't have permission to view a restricted issue + Assert.assertTrue("Number of search results not expected", resultsPage.getResults().size() == 2); + + // verify assigned to users will see both results but shouldn't be able to see details of issues not assigned to them + impersonate(USER1.getEmail()); + verifyIssueAccess(ISSUE_1, true); + verifyIssueAccess(ISSUE_2, false); + stopImpersonating(false); + + impersonate(USER2.getEmail()); + verifyIssueAccess(ISSUE_1, false); + verifyIssueAccess(ISSUE_2, true); + stopImpersonating(); + } } diff --git a/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation.query.xml b/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation.query.xml new file mode 100644 index 000000000..15aa08c77 --- /dev/null +++ b/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation.query.xml @@ -0,0 +1,36 @@ + + + + + Genetic Testing w/ Location + + + + Id + + + Sample Date + + + Area + + + Room + + + Room + + + Label + + + Comments + + + Status + + +
+
+
+
diff --git a/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation.sql b/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation.sql new file mode 100644 index 000000000..0cfa39eae --- /dev/null +++ b/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation.sql @@ -0,0 +1,10 @@ +select a.Id, + a.date, + b.Id.curLocation.area as area, + b.Id.curLocation.room as room, + b.Id.curLocation.cage as cage, + a.label, + a.comment, + b.calculated_status as LiveStatus + +from genotypesWithSignificance a, study.demographics b where a.Id = b.Id \ No newline at end of file diff --git a/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation/.qview.xml b/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation/.qview.xml new file mode 100644 index 000000000..35442b9d8 --- /dev/null +++ b/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation/.qview.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation/Genetic Testing with Current Locations.qview.xml b/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation/Genetic Testing with Current Locations.qview.xml new file mode 100644 index 000000000..0b1c76d53 --- /dev/null +++ b/onprc_reports/resources/queries/GeneticTests/genotypesWithSignificancewithLocation/Genetic Testing with Current Locations.qview.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file