diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests/SOP Delinquents.qview.xml b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests/SOP Delinquents.qview.xml
new file mode 100644
index 000000000..2f322f5ab
--- /dev/null
+++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests/SOP Delinquents.qview.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests/Training.qview.xml b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests/Training.qview.xml
new file mode 100644
index 000000000..9cdc395a6
--- /dev/null
+++ b/ONPRC_EHR_ComplianceDB/resources/queries/EHR_ComplianceDB/ComplianceProcedureRecentTests/Training.qview.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-24.007-24.008.sql b/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-24.007-24.008.sql
new file mode 100644
index 000000000..ea9b67efb
--- /dev/null
+++ b/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-24.007-24.008.sql
@@ -0,0 +1,317 @@
+
+
+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
+**
+**
+**
+*/
+
+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 h.type 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 k.expireperiod 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 (tt.expireperiod) > (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 (tt.expireperiod) 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.expireperiod) > ( datediff(month,max(pq.date), tt.reviewdate) ) ) > 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate) ) )
+
+
+
+
+ ELSE ( select (tt.expireperiod) - ( 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 h.type 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 k.expireperiod 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 (tt.expireperiod) > (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 (tt.expireperiod) 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate) )) > 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate) ) )
+
+
+ ELSE ( select (tt.expireperiod) - ( 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 h.type 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 k.expireperiod 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 (tt.expireperiod) > (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 (tt.expireperiod) 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate) )) > 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate)) )
+
+
+ ELSE ( select (tt.expireperiod) - ( 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,
+ 'Yes' 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 h.type from ehr_compliancedb.Requirements h where h.requirementname = j.requirementname) as requirement_type, ----- type trainee, or trainer
+
+ (select count(zz.date) from ehr_compliancedb.completiondates zz where zz.requirementname= j.requirementname and zz.employeeid= j.employeeid ) as timesCompleted,
+
+ (select k.expireperiod 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 (tt.expireperiod) > (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= j.requirementname and zz.employeeid= j.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= j.requirementname and zz.employeeid= j.employeeid )
+ And yy.requirementname= j.requirementname and yy.employeeid= j.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= j.requirementname and zz.employeeid= j.employeeid )
+ And yy.requirementname= j.requirementname and yy.employeeid= j.employeeid ) 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 (tt.expireperiod) 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate) )) > 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate)) )
+
+
+ ELSE ( select (tt.expireperiod) - ( 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 DECIMAL) AS MonthsUntilRenewal
+
+
+
+ from 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 )
+
+ 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
diff --git a/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-24.008-24.009.sql b/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-24.008-24.009.sql
new file mode 100644
index 000000000..54bfb6df4
--- /dev/null
+++ b/ONPRC_EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/onprc_ehr_compliancedb-24.008-24.009.sql
@@ -0,0 +1,232 @@
+
+
+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
+**
+**
+**
+*/
+
+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 h.type 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 k.expireperiod 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 (tt.expireperiod) > (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 (tt.expireperiod) 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.expireperiod) > ( datediff(month,max(pq.date), tt.reviewdate) )) > 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.expireperiod) > ( datediff(month,max(pq.date), tt.reviewdate) ) )
+
+
+
+
+ ELSE ( select (tt.expireperiod) - ( 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 h.type 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 k.expireperiod 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 (tt.expireperiod) > (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 (tt.expireperiod) 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate) )) > 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.expireperiod) > (datediff(month,max(pq.date), tt.reviewdate) ) )
+
+
+ ELSE ( select (tt.expireperiod) - ( 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,
+ 'Yes' 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 h.type from ehr_compliancedb.Requirements h where h.requirementname = j.requirementname) as requirement_type, ----- type trainee, or trainer
+ null as timesCompleted,
+ null as ExpiredPeriod,
+ null as NewExpirePeriod,
+ null as MostRecentDate,
+ '' as comment,
+ null as snooze_date,
+ null AS MonthsUntilRenewal
+
+
+
+ from 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 )
+
+ 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/requirementDetails.html b/ONPRC_EHR_ComplianceDB/resources/views/requirementDetails.html
new file mode 100644
index 000000000..6bc8fa143
--- /dev/null
+++ b/ONPRC_EHR_ComplianceDB/resources/views/requirementDetails.html
@@ -0,0 +1,94 @@
+
\ No newline at end of file
diff --git a/ONPRC_EHR_ComplianceDB/resources/views/requirementDetails.view.xml b/ONPRC_EHR_ComplianceDB/resources/views/requirementDetails.view.xml
new file mode 100644
index 000000000..8fe8cdeeb
--- /dev/null
+++ b/ONPRC_EHR_ComplianceDB/resources/views/requirementDetails.view.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ 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 a03021ffb..6177e2f77 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.007;
+ return 24.009;
}
@Override
diff --git a/onprc_ehr/resources/schemas/dbscripts/sqlserver/onprc_ehr-24.005-24.006.sql b/onprc_ehr/resources/schemas/dbscripts/sqlserver/onprc_ehr-24.005-24.006.sql
new file mode 100644
index 000000000..3a7cb2a6b
--- /dev/null
+++ b/onprc_ehr/resources/schemas/dbscripts/sqlserver/onprc_ehr-24.005-24.006.sql
@@ -0,0 +1,14 @@
+CREATE TABLE onprc_ehr.procedure_default_blood (
+ rowid int identity(1,1),
+ procedureid int,
+ sampletype varchar(300) Null,
+ additionalServices varchar(1000) Null,
+ reason varchar(300) Null,
+ instructions varchar(2000) Null,
+ chargetype varchar(400) Null
+
+
+ CONSTRAINT PK_procedure_default_blood PRIMARY KEY (rowid)
+)
+
+GO
\ No newline at end of file
diff --git a/onprc_ehr/resources/schemas/onprc_ehr.xml b/onprc_ehr/resources/schemas/onprc_ehr.xml
index 5f5b3a307..47fc9a195 100644
--- a/onprc_ehr/resources/schemas/onprc_ehr.xml
+++ b/onprc_ehr/resources/schemas/onprc_ehr.xml
@@ -1456,6 +1456,36 @@
+
+
+ DETAILED
+ Default Surgical Observations Per Procedure
+ rowid
+
+
+ true
+
+
+
+ ehr_lookups
+ procedure
+ rowid
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/onprc_ehr/resources/web/onprc_ehr/model/sources/Surgery.js b/onprc_ehr/resources/web/onprc_ehr/model/sources/Surgery.js
index 1197a08e6..f47340a4d 100644
--- a/onprc_ehr/resources/web/onprc_ehr/model/sources/Surgery.js
+++ b/onprc_ehr/resources/web/onprc_ehr/model/sources/Surgery.js
@@ -124,6 +124,11 @@ EHR.model.DataModelManager.registerMetadata('onprc_Surgery', {
}
}
},
+ 'study.blood': {
+ reason: {
+ defaultValue: 'Surgical'
+ }
+ },
'ehr.encounter_summaries': {
category: {
defaultValue: 'Narrative'
diff --git a/onprc_ehr/resources/web/onprc_ehr/panel/SnapshotPanel.js b/onprc_ehr/resources/web/onprc_ehr/panel/SnapshotPanel.js
index 8410e32e6..5037999bb 100644
--- a/onprc_ehr/resources/web/onprc_ehr/panel/SnapshotPanel.js
+++ b/onprc_ehr/resources/web/onprc_ehr/panel/SnapshotPanel.js
@@ -40,27 +40,6 @@ Ext4.define('onprc_ehr.panel.SnapshotPanel', {
this.setLoading(true);
this.loadData();
}
-
- this.on('afterrender', function() {
-
- var displayField = this.down('#flags');
- if (displayField && displayField.getEl()) {
-
- var anchors = [displayField.getEl('onprcFlagsLink'), displayField.getEl('onprcBehaviorFlagsLink')];
-
- for (let i = 0; i < anchors.length; i++) {
- let anchor = anchors[i];
- if (anchor) {
- Ext4.get(anchor).on('click', function(e) {
- e.preventDefault();
- if (anmId) {
- EHR.Utils.showFlagPopup(anmId, this);
- }
- });
- }
- }
- }
- }, this);
},
getBaseItems: function(){
@@ -112,7 +91,23 @@ Ext4.define('onprc_ehr.panel.SnapshotPanel', {
},{
xtype: 'displayfield',
fieldLabel: 'Behavior Alert' ,
- name: 'behaviorflag'
+ name: 'behaviorflag',
+ listeners: {
+ change: function(field, newValue, oldValue){
+ let anchor = field.getEl('onprcBehaviorFlagsLink');
+ if (this?.up('panel')?.up('panel')) {
+ let anmId = this.up('panel').up('panel').subjectId;
+ if (anchor) {
+ Ext4.get(anchor).on('click', function(e) {
+ e.preventDefault();
+ if (anmId) {
+ EHR.Utils.showFlagPopup(anmId, this);
+ }
+ });
+ }
+ }
+ }
+ }
}]
},{
xtype: 'container',
@@ -153,7 +148,23 @@ Ext4.define('onprc_ehr.panel.SnapshotPanel', {
xtype: 'displayfield',
fieldLabel: 'Flags',
name: 'flags',
- itemId: 'flags'
+ itemId: 'flags',
+ listeners: {
+ change: function(field, newValue, oldValue){
+ let anchor = field.getEl('onprcFlagsLink');
+ if (this?.up('panel')?.up('panel')) {
+ let anmId = this.up('panel').up('panel').subjectId;
+ if (anchor) {
+ Ext4.get(anchor).on('click', function(e) {
+ e.preventDefault();
+ if (anmId) {
+ EHR.Utils.showFlagPopup(anmId, this);
+ }
+ });
+ }
+ }
+ }
+ }
},{
xtype: 'displayfield',
fieldLabel: 'Last TB Date',
@@ -733,12 +744,10 @@ Ext4.define('onprc_ehr.panel.SnapshotPanel', {
}
}
- toSet['flags'] = values.length ? '' + values.join('
') + '' : null;
-
- behavevalues = ['test'];
+ toSet['flags'] = values.length ? '' + values.join('
') + '' : null;
if (behavevalues.length) {
- toSet['behaviorflag'] = '' + behavevalues.join('
') + '';
+ toSet['behaviorflag'] = '' + behavevalues.join('
') + '';
}
else
{
diff --git a/onprc_ehr/resources/web/onprc_ehr/panel/SurgeryInstructionsPanel.js b/onprc_ehr/resources/web/onprc_ehr/panel/SurgeryInstructionsPanel.js
new file mode 100644
index 000000000..d5b230780
--- /dev/null
+++ b/onprc_ehr/resources/web/onprc_ehr/panel/SurgeryInstructionsPanel.js
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014-2019 LabKey Corporation
+ *
+ * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
+ */
+Ext4.define('ONPRC_EHR.panel.SurgeryInstructionsPanel', {
+ extend: 'Ext.panel.Panel',
+ alias: 'widget.onprc_ehr-surgeryinstructionspanel',
+
+ initComponent: function(){
+ var buttons = [];
+ LDK.Assert.assertNotEmpty('No data entry panel', this.dataEntryPanel);
+ var btnCfg = EHR.DataEntryUtils.getDataEntryFormButton('APPLYENCOUNTERDEFAULTSAMENDED');
+ if (btnCfg){
+ btnCfg = this.dataEntryPanel.configureButton(btnCfg);
+ if (btnCfg){
+ btnCfg.text = 'Add Procedure Defaults';
+ buttons.push(btnCfg);
+ }
+ }
+
+ Ext4.apply(this, {
+ defaults: {
+
+ },
+ bodyStyle: 'padding: 5px;',
+ title: 'Instructions',
+ items: [{
+ html: 'This form is designed for surgery entry. The top section contains basic information on the procedure(s). The bottom sections can be used to enter the narrative, medications, etc. Once you enter entered the animal(s) and procedures, use the bottom below to apply defaults to the other sections for those procedures.',
+ maxWidth: Ext4.getBody().getWidth() * 0.8,
+ style: 'padding-top: 10px;padding-bottom: 10px;',
+ border: false
+ },btnCfg]
+ });
+
+ this.callParent(arguments);
+ }
+
+});
\ No newline at end of file
diff --git a/onprc_ehr/resources/web/onprc_ehr/window/AddProcedureDefaultsWindow.js b/onprc_ehr/resources/web/onprc_ehr/window/AddProcedureDefaultsWindow.js
new file mode 100644
index 000000000..6ebab410e
--- /dev/null
+++ b/onprc_ehr/resources/web/onprc_ehr/window/AddProcedureDefaultsWindow.js
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 2014-2019 LabKey Corporation
+ *
+ * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
+ */
+/**
+ * @cfg dataEntryPanel
+ * @cfg encountersStore
+ * @cfg [] targetTabs
+ */
+Ext4.define('ONPRC_EHR.window.AddProcedureDefaultsWindow', {
+ extend: 'Ext.window.Window',
+ applyStaffTemplate: false,
+ allowAddWeightRecord: false,
+
+ initComponent: function(){
+ Ext4.applyIf(this, {
+ modal: true,
+ width: 750,
+ closeAction: 'destroy',
+ title: ((!this.targetTabs || this.targetTabs.length != 1) ? 'Add Procedure Defaults' : 'Add Procedure Defaults For Section'),
+ bodyStyle: 'padding: 5px;',
+ defaults: {
+ border: false
+ },
+ items: [{
+ html: 'This helper allows you to populate expected rows based on the procedures requested above. A list of the procedures and expected values are below.',
+ style: 'margin-bottom: 10px;'
+ },{
+ itemId: 'services',
+ items: [{
+ border: false,
+ html: 'Loading...'
+ }]
+ }],
+ buttons: [{
+ text: 'Submit',
+ itemId: 'submitBtn',
+ disabled: true,
+ scope: this,
+ handler: this.onSubmit
+ },{
+ text: 'Close',
+ handler: function(btn){
+ btn.up('window').close();
+ }
+ }]
+ });
+
+ if (!this.targetTabs){
+ this.targetTabs = [];
+ this.applyStaffTemplate = true;
+ this.allowAddWeightRecord = true;
+ Ext4.each(this.dataEntryPanel.formConfig.sections, function(s){
+ if (this.tableNameMap[s.name]){
+ var item = this.dataEntryPanel.getSectionByName(s.name);
+ LDK.Assert.assertNotEmpty('Unable to find panel: ' + s.name, item);
+ if (item != null)
+ this.targetTabs.push(item);
+ }
+ }, this);
+ }
+
+ this.inferPanels();
+
+ this.callParent();
+
+ this.on('beforeshow', function(){
+ if (!this.encountersRecords.length){
+ Ext4.Msg.alert('No Records', 'There are no available procedures, nothing to add');
+ return false;
+ }
+ }, this);
+ },
+
+ inferPanels: function(){
+ this.encountersRecords = this.getEncountersRecords();
+ if (!this.encountersRecords.length){
+ return;
+ }
+
+ var services = {};
+ Ext4.Array.forEach(this.encountersRecords, function(r){
+ services[r.get('procedureid')] = true;
+ }, this);
+
+ this.loadServices(Ext4.Object.getKeys(services));
+ },
+
+ getEncountersRecords: function(){
+ var records = [];
+ this.encountersStore.each(function(r){
+ if (r.get('Id') && r.get('date') && r.get('procedureid')){
+ records.push(r);
+ }
+ }, this);
+
+ return records;
+ },
+
+ getExistingParentIds: function(){
+ var keys = {};
+ Ext4.Array.forEach(this.targetTabs, function(tab){
+ keys[tab.formConfig.name] = {};
+ tab.store.each(function(r){
+ if (r.get('parentid'))
+ keys[tab.formConfig.name][r.get('parentid')] = true;
+ }, this);
+ }, this);
+
+ return keys
+ },
+
+ tableNameMap: {
+ 'Drug Administration': {
+ schemaName: 'ehr_lookups',
+ queryName: 'procedure_default_treatments',
+ columns: 'procedureid,code,qualifier,route,frequency,volume,vol_units,dosage,dosage_units,concentration,conc_units,amount,amount_units'
+ },
+ encounter_summaries: {
+ schemaName: 'ehr_lookups',
+ queryName: 'procedure_default_comments',
+ columns: 'procedureid,comment',
+ targetColumns: 'procedureid,remark'
+ },
+
+ blood: {
+ schemaName: 'onprc_ehr',
+ queryName: 'procedure_default_blood',
+ columns: 'procedureid,sampletype,chargetype,reason,additionalServices',
+
+ },
+ snomed_tags: {
+ schemaName: 'ehr_lookups',
+ queryName: 'procedure_default_codes',
+ columns: 'procedureid,code,qualifier',
+ sort: 'sort_order'
+ }
+ },
+
+ loadServices: function(){
+ var multi = new LABKEY.MultiRequest();
+ var totalRequests = 0;
+ this.panelMap = {};
+ Ext4.Array.forEach(this.targetTabs, function(tab){
+ var cfg = this.tableNameMap[tab.formConfig.name];
+ if (cfg){
+ totalRequests++;
+ multi.add(LABKEY.Query.selectRows, {
+ schemaName: cfg.schemaName,
+ queryName: cfg.queryName,
+ requiredVersion: 9.1,
+ columns: cfg.columns,
+ failure: LDK.Utils.getErrorCallback(),
+ success: function(results){
+ this.panelMap[tab.formConfig.name] = {};
+ if (results && results.rows && results.rows.length){
+ Ext4.Array.forEach(results.rows, function(r){
+ var row = new LDK.SelectRowsRow(r);
+ if (!this.panelMap[tab.formConfig.name][row.getValue('procedureid')])
+ this.panelMap[tab.formConfig.name][row.getValue('procedureid')] = [];
+
+ this.panelMap[tab.formConfig.name][row.getValue('procedureid')].push(row);
+ }, this);
+ }
+ },
+ scope: this
+ });
+ }
+ }, this);
+
+ LDK.Assert.assertTrue('No matching tables found in AddProcedureDefaultsWindow', totalRequests > 0);
+
+ if (totalRequests > 0)
+ multi.send(this.onLoad, this);
+ else {
+ //this should never actually get called
+ this.on('beforeshow', function(window){
+ Ext4.Msg.alert('No Records', 'Add defaults is not supported for this section.');
+ return false;
+ }, this);
+ }
+ },
+
+ onLoad: function(){
+ var toAdd= [{
+ html: 'Id'
+ },{
+ html: 'Date'
+ },{
+ html: 'Choose Template'
+ },{
+ html: 'Ignore'
+ }];
+
+ var keys = this.getExistingParentIds();
+ Ext4.Array.forEach(this.encountersRecords, function(r){
+ toAdd.push({
+ html: r.get('Id'),
+ width: 60
+ });
+ toAdd.push({
+ html: Ext4.Date.format(r.get('date'), LABKEY.extDefaultDateFormat),
+ width: 110
+ });
+
+ var ignoreId = 'ignore_' + Ext4.id();
+ toAdd.push({
+ xtype: 'labkey-combo',
+ anyMatch: true,
+ width: 250,
+ boundRecord: r,
+ ignoreCheckbox: ignoreId,
+ displayField: 'name',
+ valueField: 'rowid',
+ forceSelection: true,
+ queryMode: 'local',
+ value: r.get('procedureid'),
+ store: {
+ type: 'labkey-store',
+ schemaName: 'ehr_lookups',
+ queryName: 'procedures',
+ columns: 'name,rowid',
+ autoLoad: true
+ }
+ });
+ toAdd.push({
+ xtype: 'checkbox',
+ width: 80,
+ itemId: ignoreId,
+ checked: this.targetTabs.length == 1 ? keys[this.targetTabs[0].formConfig.name][r.get('objectid')] : false
+ });
+ }, this);
+
+ var target = this.down('#services');
+
+ target.removeAll();
+ target.add({
+ border: false,
+ itemId: 'fieldPanel',
+ layout: {
+ type: 'table',
+ columns: 4
+ },
+ defaults: {
+ border: false,
+ height: '15px',
+ style: 'padding: 2px;margin-right: 4px;vertical-align:text-top;'
+ },
+ items: toAdd
+ });
+
+ if (this.allowAddWeightRecord){
+ this.add({
+ xtype: 'checkbox',
+ fieldLabel: 'Add Weight Record',
+ itemId: 'addWeightRecord',
+ checked: true
+ });
+ }
+
+ this.down('#submitBtn').setDisabled(false);
+ },
+
+ onSubmit: function(){
+ var hasRecords = false;
+ var distinctIds = [];
+ var parentIdMap = {};
+
+ this.down('#fieldPanel').items.each(function(item){
+ if (item.boundRecord){
+ var ignoreCheckbox = this.down('#' + item.ignoreCheckbox);
+ if (ignoreCheckbox.getValue()){
+ return;
+ }
+
+ distinctIds.push(item.boundRecord.get('Id'));
+ parentIdMap[item.boundRecord.get('Id')] = parentIdMap[item.boundRecord.get('Id')] || [];
+ parentIdMap[item.boundRecord.get('Id')].push(item.boundRecord.get('objectid'));
+
+ var panel = item.getValue();
+ Ext4.Array.forEach(this.targetTabs, function(targetTab){
+ var rows;
+ var records = [];
+
+ if (panel && this.panelMap[targetTab.formConfig.name] && this.panelMap[targetTab.formConfig.name][panel]){
+ rows = this.panelMap[targetTab.formConfig.name][panel];
+ }
+
+ if (rows && rows.length){
+ Ext4.Array.forEach(rows, function(row){
+ var data = {
+ Id: item.boundRecord.get('Id'),
+ date: item.boundRecord.get('date'),
+ project: item.boundRecord.get('project'),
+ encounterid: item.boundRecord.get('objectid'),
+ parentid: item.boundRecord.get('objectid')
+ };
+
+ var cfg = this.tableNameMap[targetTab.formConfig.name];
+ if (cfg && cfg.columns){
+ var columns = cfg.columns.split(',');
+ var targetColumns = (cfg.targetColumns || cfg.columns).split(',');
+ Ext4.Array.forEach(columns, function(col, idx){
+ if (!Ext4.isEmpty(row.getValue(col))){
+ data[targetColumns[idx]] = row.getValue(col);
+ }
+ }, this);
+ }
+
+ records.push(targetTab.store.createModel(data));
+ }, this);
+
+ if (records.length){
+ targetTab.store.add(records);
+ hasRecords = true;
+ }
+ }
+ }, this);
+ }
+ }, this);
+
+ //add weight
+ distinctIds = Ext4.unique(distinctIds);
+ if (this.allowAddWeightRecord && this.down('#addWeightRecord').getValue()){
+ var weightStore = this.dataEntryPanel.storeCollection.getClientStoreByName('weight');
+ LDK.Assert.assertNotEmpty('Unable to find weight store in AddProcedureDefaultsWindow', weightStore);
+ var toAdd = [];
+ Ext4.Array.forEach(distinctIds, function(id){
+ //arbitrarily assign parentid based on the first matching procedure, in the case of multiple procedures
+ toAdd.push(weightStore.createModel({
+ Id: id,
+ parentid: parentIdMap[id][0]
+ }));
+ }, this);
+
+ if (toAdd.length){
+ weightStore.add(toAdd);
+ }
+ }
+
+ //add templates
+ if (this.applyStaffTemplate){
+ var majorSurg = [];
+ var minorSurg = [];
+ var procedureStore = EHR.DataEntryUtils.getProceduresStore();
+ Ext4.Array.forEach(this.encountersRecords, function(r){
+ if (r.get('procedureid')){
+ var obj = {
+ Id: r.get('Id'),
+ date: r.get('date'),
+ parentid: r.get('objectid')
+ }
+
+ var recIdx = procedureStore.findExact('rowid', r.get('procedureid'));
+ LDK.Assert.assertTrue('Unable to find procedure with rowid: ' + r.get('procedureid'), recIdx > -1);
+ if (recIdx > -1){
+ var procRec = procedureStore.getAt(recIdx);
+
+ if (procRec.get('major')){
+ majorSurg.push(obj);
+ }
+ else {
+ minorSurg.push(obj);
+ }
+ }
+ }
+ }, this);
+
+ this.minorSurgToLoad = minorSurg;
+ this.majorSurgToLoad = majorSurg;
+
+ if (minorSurg.length || majorSurg.length){
+ this.loadTemplateIds();
+ }
+ else {
+ this.finalize(true);
+ }
+ }
+ else {
+ this.finalize(hasRecords);
+ }
+ },
+
+ loadTemplateIds: function(){
+ LABKEY.Query.selectRows({
+ schemaName: 'ehr',
+ queryName: 'formtemplates',
+ requiredVersion: 9.1,
+ scope: this,
+ filterArray: [
+ LABKEY.Filter.create('title', 'Major Surgery;Minor Surgery', LABKEY.Filter.Types.EQUALS_ONE_OF),
+ LABKEY.Filter.create('category', 'Section', LABKEY.Filter.Types.EQUAL),
+ LABKEY.Filter.create('formtype', 'encounter_participants', LABKEY.Filter.Types.EQUAL)
+
+ ],
+ failure: LDK.Utils.getErrorCallback(),
+ success: function(results){
+ if (results && results.rows && results.rows.length){
+ Ext4.Array.forEach(results.rows, function(r){
+ var row = new LDK.SelectRowsRow(r);
+ if (row.getValue('title') == 'Major Surgery'){
+ this.majorSurgTemplateId = row.getValue('entityid');
+ }
+ else if (row.getValue('title') == 'Minor Surgery'){
+ this.minorSurgTemplateId = row.getValue('entityid');
+ }
+ }, this);
+
+ LDK.Assert.assertEquality('Wrong row count found in AddProcedureDefaultsWindow', 2, results.rows.length);
+ }
+
+ LDK.Assert.assertNotEmpty('Unable to find template for Major Surgery', this.majorSurgTemplateId);
+ LDK.Assert.assertNotEmpty('Unable to find template for Minor Surgery', this.minorSurgTemplateId);
+
+ this.loadMinorSurg();
+ }
+ })
+ },
+
+ loadMinorSurg: function(){
+ if (this.minorSurgToLoad && this.minorSurgToLoad.length){
+ EHR.window.ApplyTemplateWindow.loadTemplateRecords(this.afterLoadMinorSurgTemplate, this, this.dataEntryPanel.storeCollection, this.minorSurgTemplateId, this.minorSurgToLoad);
+ }
+ else {
+ this.afterLoadMinorSurgTemplate();
+ }
+ },
+
+ queueTemplateRecords: function(recMap){
+ if (!recMap)
+ return;
+
+ this.templateRecordsToAdd = this.templateRecordsToAdd || {};
+ for (var i in recMap){
+ this.templateRecordsToAdd[i] = this.templateRecordsToAdd[i] || [];
+ this.templateRecordsToAdd[i] = this.templateRecordsToAdd[i].concat(recMap[i]);
+ }
+ },
+
+ addQueuedTemplateRecords: function(){
+ if (!this.templateRecordsToAdd)
+ return;
+
+ for (var i in this.templateRecordsToAdd){
+ var store = Ext4.StoreMgr.get(i);
+ store.add(this.templateRecordsToAdd[i]);
+ delete this.templateRecordsToAdd[i];
+ }
+ },
+
+ afterLoadMinorSurgTemplate: function(recMap){
+ delete this.minorSurgToLoad;
+
+ this.queueTemplateRecords(recMap);
+
+ if (!this.majorSurgToLoad || !this.majorSurgToLoad.length){
+ this.afterLoadMajorSurgTemplate();
+ }
+ else {
+ EHR.window.ApplyTemplateWindow.loadTemplateRecords(this.afterLoadMajorSurgTemplate, this, this.dataEntryPanel.storeCollection, this.majorSurgTemplateId, this.majorSurgToLoad);
+ }
+ },
+
+ afterLoadMajorSurgTemplate: function(recMap){
+ delete this.majorSurgToLoad;
+ this.queueTemplateRecords(recMap);
+
+ this.finalize(true);
+ },
+
+ finalize: function(hasRecords){
+ this.close();
+ this.addQueuedTemplateRecords();
+
+ if (!this.applyStaffTemplate && !hasRecords){
+ Ext4.Msg.alert('No Records', 'There are no records to add');
+ }
+ }
+});
+
+EHR.DataEntryUtils.registerGridButton('ADDPROCEDUREDEFAULTSAMENDED', function(config){
+ return Ext4.Object.merge({
+ text: 'Add Procedure Defaults',
+ xtype: 'button',
+ tooltip: 'Click to copy records from the encounters section',
+ handler: function(btn){
+ var grid = btn.up('grid');
+ LDK.Assert.assertNotEmpty('Unable to find grid in ADDPROCEDUREDEFAULTSAMENDED button', grid);
+
+ var panel = grid.up('ehr-dataentrypanel');
+ LDK.Assert.assertNotEmpty('Unable to find dataEntryPanel in AADDPROCEDUREDEFAULTSAMENDED button', panel);
+
+ var store = panel.storeCollection.getClientStoreByName('encounters');
+ LDK.Assert.assertNotEmpty('Unable to find encounters store in ADDPROCEDUREDEFAULTSAMENDED button', store);
+
+ if (store){
+ Ext4.create('ONPRC_EHR.window.AddProcedureDefaultsWindow', {
+ dataEntryPanel: panel,
+ targetTabs: [grid],
+ encountersStore: store
+ }).show();
+ }
+ }
+ });
+});
+
+EHR.DataEntryUtils.registerDataEntryFormButton('APPLYENCOUNTERDEFAULTSAMENDED', {
+ text: 'Add Procedure Defaults',
+ xtype: 'button',
+ tooltip: 'Click to copy records from the encounters section',
+ handler: function(btn){
+ var panel = btn.up('ehr-dataentrypanel');
+ LDK.Assert.assertNotEmpty('Unable to find dataEntryPanel in APPLYENCOUNTERDEFAULTSAMENDED button', panel);
+
+ var store = panel.storeCollection.getClientStoreByName('encounters');
+ LDK.Assert.assertNotEmpty('Unable to find encounters store in APPLYENCOUNTERDEFAULTSAMENDED button', store);
+
+ if (store){
+ Ext4.create('ONPRC_EHR.window.AddProcedureDefaultsWindow', {
+ dataEntryPanel: panel,
+ encountersStore: store
+ }).show();
+ }
+ }
+});
\ 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 5ec60e1d9..ca89952d2 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/ONPRC_EHRModule.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/ONPRC_EHRModule.java
@@ -126,7 +126,7 @@ public String getName()
@Override
public @Nullable Double getSchemaVersion()
{
- return 24.005;
+ return 24.006;
}
@Override
diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/EncounterChildFormSection.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/EncounterChildFormSection.java
index 11d1a2380..66b37ae97 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/EncounterChildFormSection.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/EncounterChildFormSection.java
@@ -40,7 +40,9 @@ public EncounterChildFormSection(String schemaName, String queryName, String lab
addClientDependency(ClientDependency.supplierFromPath("ehr/buttons/encounterButtons.js"));
addClientDependency(ClientDependency.supplierFromPath("ehr/model/sources/EncounterChild.js"));
addClientDependency(ClientDependency.supplierFromPath("ehr/window/EncounterAddRecordWindow.js"));
- addClientDependency(ClientDependency.supplierFromPath("ehr/window/AddProcedureDefaultsWindow.js"));
+
+// Modified: 2-13-2025 R. Blasa
+ addClientDependency(ClientDependency.supplierFromPath("onprc_ehr/window/AddProcedureDefaultsWindow.js"));
addConfigSource("Encounter");
addConfigSource("EncounterChild");
@@ -67,7 +69,7 @@ public List getTbarButtons()
List defaultButtons = new ArrayList<>();
if (_allowAddDefaults)
- defaultButtons.add("ADDPROCEDUREDEFAULTS");
+ defaultButtons.add("ADDPROCEDUREDEFAULTSAMENDED");
defaultButtons.addAll(super.getTbarButtons());
defaultButtons.remove("ADDANIMALS");
diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/SingleSurgeryFormType.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/SingleSurgeryFormType.java
index 495767b0b..d6cb8939b 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/SingleSurgeryFormType.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/SingleSurgeryFormType.java
@@ -46,7 +46,7 @@ public class SingleSurgeryFormType extends EncounterForm
public SingleSurgeryFormType(DataEntryFormContext ctx, Module owner)
{
super(ctx, owner, NAME, "Surgery", "Surgery", Arrays.asList(
- new NonStoreFormSection("Instructions", "Instructions", "ehr-surgeryinstructionspanel", Arrays.asList(ClientDependency.supplierFromPath("ehr/panel/SurgeryInstructionsPanel.js"))),
+ new NonStoreFormSection("Instructions", "Instructions", "onprc_ehr-surgeryinstructionspanel", Arrays.asList(ClientDependency.supplierFromPath("onprc_ehr/panel/SurgeryInstructionsPanel.js"))),
new TaskFormSection(),
new ClinicalEncountersFormPanelSection("Surgery"),
new ExtendedAnimalDetailsFormSection(),
diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/SurgeryFormType.java b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/SurgeryFormType.java
index 82e6c2144..a20b1847e 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/SurgeryFormType.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/dataentry/SurgeryFormType.java
@@ -47,7 +47,7 @@ public class SurgeryFormType extends EncounterForm
public SurgeryFormType(DataEntryFormContext ctx, Module owner)
{
super(ctx, owner, NAME, "Surgeries", "Surgery", Arrays.asList(
- new NonStoreFormSection("Instructions", "Instructions", "ehr-surgeryinstructionspanel", Arrays.asList(ClientDependency.supplierFromPath("ehr/panel/SurgeryInstructionsPanel.js"))),
+ new NonStoreFormSection("Instructions", "Instructions", "onprc_ehr-surgeryinstructionspanel", Arrays.asList(ClientDependency.supplierFromPath("onprc_ehr/panel/SurgeryInstructionsPanel.js"))),
new TaskFormSection(),
new ClinicalEncountersFormSection(),
new ExtendedAnimalDetailsFormSection(),
diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/issues/RestrictedIssueProviderImpl.java b/onprc_ehr/src/org/labkey/onprc_ehr/issues/RestrictedIssueProviderImpl.java
index fdc119b09..be3ade1ec 100644
--- a/onprc_ehr/src/org/labkey/onprc_ehr/issues/RestrictedIssueProviderImpl.java
+++ b/onprc_ehr/src/org/labkey/onprc_ehr/issues/RestrictedIssueProviderImpl.java
@@ -96,21 +96,6 @@ public boolean hasPermission(User user, @NotNull Issue issue, List relate
return false;
}
}
-
- // the user must also have access to all related issues
- for (Issue related : relatedIssues)
- {
- Container relatedContainer = ContainerManager.getForId(related.getContainerId());
- if (relatedContainer != null && isRestrictedIssueTracker(relatedContainer, related.getIssueDefName()))
- {
- Group relatedGroup = getRestrictedIssueListGroup(relatedContainer, related.getIssueDefName());
- if (!checkAccess(user, related, relatedGroup))
- {
- errors.add(new SimpleValidationError(String.format("A related issue : %d is in a restricted issue list. You do not have access to that issue", related.getIssueId())));
- return false;
- }
- }
- }
return true;
}
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
new file mode 100644
index 000000000..7e54dae2c
--- /dev/null
+++ b/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_RestrictedIssueTest.java
@@ -0,0 +1,268 @@
+package org.labkey.test.tests.onprc_ehr;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.labkey.test.BaseWebDriverTest;
+import org.labkey.test.Locator;
+import org.labkey.test.TestTimeoutException;
+import org.labkey.test.categories.EHR;
+import org.labkey.test.categories.ONPRC;
+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.util.IssuesHelper;
+import org.labkey.test.util.SqlserverOnlyTest;
+import org.labkey.test.util.TestUser;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@Category({EHR.class, ONPRC.class})
+public class ONPRC_RestrictedIssueTest extends BaseWebDriverTest implements SqlserverOnlyTest
+{
+ private final IssuesHelper _issuesHelper;
+
+ // constants
+ private static final TestUser USER1 = new TestUser("user1_issuetest@issues.test");
+ private static final TestUser USER2 = new TestUser("user2_issuetest@issues.test");
+ private static final TestUser ISSUE_CREATOR = new TestUser("issue_creator_issuetest@issues.test");
+ private static final TestUser FOLDER_ADMIN = new TestUser("folder_admin_issuetest@issues.test");
+
+ private static final String RESTRICTED_ISSUES_LIST = "restricted-issues";
+ private static final String UNRESTRICTED_ISSUES_LIST = "unrestricted-issues";
+ private static final String ACCESS_ERROR_MSG = "This issue is in a restricted issue list. You do not have access to this issue";
+
+ public ONPRC_RestrictedIssueTest()
+ {
+ _issuesHelper = new IssuesHelper(this);
+ }
+
+ @BeforeClass
+ public static void doSetup()
+ {
+ ONPRC_RestrictedIssueTest initTest = getCurrentTest();
+ initTest.doInit();
+ }
+
+ public void doInit()
+ {
+ _containerHelper.createProject(getProjectName(), null);
+
+ // Create test users
+ USER1.create(this).addPermission("Editor", getProjectName());
+ USER2.create(this).addPermission("Editor", getProjectName());
+ ISSUE_CREATOR.create(this).addPermission("Editor", getProjectName());
+ FOLDER_ADMIN.create(this).addPermission("Folder Administrator", getProjectName());
+
+ // Add issue list definitions
+ _issuesHelper.createNewIssuesList(RESTRICTED_ISSUES_LIST, _containerHelper, true, false, false);
+ waitAndClickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ _issuesHelper.goToAdmin();
+ _issuesHelper.setRestrictedIssueList(true);
+ _issuesHelper.setIssueAssignmentList("Site: Users");
+ clickButton("Save");
+
+ goToProjectHome();
+ _issuesHelper.createNewIssuesList(UNRESTRICTED_ISSUES_LIST, _containerHelper, false, false, false);
+ waitAndClickAndWait(Locator.linkContainingText(UNRESTRICTED_ISSUES_LIST));
+ _issuesHelper.goToAdmin();
+ _issuesHelper.setIssueAssignmentList("Site: Users");
+ clickButton("Save");
+ }
+
+ @Override
+ protected void doCleanup(boolean afterTest) throws TestTimeoutException
+ {
+ _userHelper.deleteUsers(false, USER1, USER2, ISSUE_CREATOR, FOLDER_ADMIN);
+ _containerHelper.deleteProject(getProjectName(), afterTest);
+ }
+
+ @Override
+ public List getAssociatedModules()
+ {
+ return Arrays.asList("ehr", "onprc_ehr");
+ }
+
+ @Override
+ protected String getProjectName()
+ {
+ return "RestrictedIssuesVerifyProject";
+ }
+
+ @Test
+ public void restrictedIssueTest()
+ {
+ goToProjectHome();
+
+ // create a few issues in the restricted list
+ impersonate(ISSUE_CREATOR.getEmail());
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ DetailsPage detailsPage = _issuesHelper.addIssue(String.format("Restricted issue assigned to (%s)", USER1.getUserDisplayName()), USER1.getUserDisplayName());
+ final String ISSUE_1 = detailsPage.getIssueId();
+ InsertPage insertPage = detailsPage.clickCreateNewIssue();
+ insertPage.title().set(String.format("Restricted issue assigned to (%s)", USER2.getUserDisplayName()));
+ insertPage.assignedTo().set(USER2.getUserDisplayName());
+ insertPage.save();
+ final String ISSUE_2 = insertPage.getIssueId();
+ stopImpersonating();
+
+ // verify site admins can see both issues (but not folder admins)
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ verifyIssueAccess(ISSUE_1, true);
+ verifyIssueAccess(ISSUE_2, true);
+
+ impersonate(FOLDER_ADMIN.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ verifyIssueAccess(ISSUE_1, false);
+ verifyIssueAccess(ISSUE_2, false);
+ stopImpersonating();
+
+ // creators can see all of the issues they opened
+ impersonate(ISSUE_CREATOR.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ verifyIssueAccess(ISSUE_1, true);
+ verifyIssueAccess(ISSUE_2, true);
+ stopImpersonating();
+
+ // users can view issues assigned to them
+ impersonate(USER1.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ verifyIssueAccess(ISSUE_1, true);
+ verifyIssueAccess(ISSUE_2, false);
+ stopImpersonating();
+
+ // verify notify list grants access
+ UpdatePage page = UpdatePage.beginAt(this, ISSUE_2);
+ page.notifyList().set(USER1.getEmail());
+ page.save();
+ impersonate(USER1.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ verifyIssueAccess(ISSUE_1, true);
+ verifyIssueAccess(ISSUE_2, true);
+ stopImpersonating();
+ }
+
+ private void verifyIssueAccess(String issueID, boolean shouldHaveAccess)
+ {
+ Locator issueLink = getIssueLinkLocator(issueID);
+ waitForElement(issueLink, defaultWaitForPage);
+ pushLocation();
+ waitAndClickAndWait(issueLink);
+ if (shouldHaveAccess)
+ assertTextNotPresent(ACCESS_ERROR_MSG);
+ else
+ assertTextPresent(ACCESS_ERROR_MSG);
+ popLocation();
+ }
+
+ @Test
+ public void relatedIssueTest()
+ {
+ goToProjectHome();
+
+ // create 2 issues related to each other
+ impersonate(ISSUE_CREATOR.getEmail());
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ DetailsPage detailsPage = _issuesHelper.addIssue(String.format("Restricted issue assigned to (%s)", USER1.getUserDisplayName()), USER1.getUserDisplayName());
+ final String ISSUE_1 = detailsPage.getIssueId();
+ InsertPage insertPage = detailsPage.clickCreateNewIssue();
+ insertPage.title().set(String.format("Restricted issue assigned to (%s)", USER2.getUserDisplayName()));
+ insertPage.assignedTo().set(USER2.getUserDisplayName());
+ insertPage.related().set(ISSUE_1);
+ insertPage.save();
+ final String ISSUE_2 = insertPage.getIssueId();
+ stopImpersonating();
+
+ // verify creator sees both all issues and their relationships
+ impersonate(ISSUE_CREATOR.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ verifyRelatedIssueAccess(ISSUE_1, ISSUE_2, true);
+ verifyRelatedIssueAccess(ISSUE_2, ISSUE_1, true);
+ stopImpersonating();
+
+ // verify users can open issue assigned to them but not see the related issue
+ impersonate(USER1.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ verifyRelatedIssueAccess(ISSUE_1, ISSUE_2, false);
+ // shouldn't be able to access the other issue at all
+ verifyIssueAccess(ISSUE_2, false);
+ stopImpersonating();
+
+ impersonate(USER2.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(RESTRICTED_ISSUES_LIST));
+ verifyRelatedIssueAccess(ISSUE_2, ISSUE_1, false);
+ verifyIssueAccess(ISSUE_1, false);
+ stopImpersonating();
+
+ // create issues in the unrestricted issue list and relate them to issues in the other list
+ impersonate(ISSUE_CREATOR.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(UNRESTRICTED_ISSUES_LIST));
+ // issue related to both restricted issues
+ detailsPage = _issuesHelper.addIssue(String.format("UnRestricted issue assigned to (%s)", USER1.getUserDisplayName()),
+ USER1.getUserDisplayName(), Collections.singletonMap("related", String.join(",", List.of(ISSUE_1, ISSUE_2))));
+ final String ISSUE_3 = detailsPage.getIssueId();
+ stopImpersonating();
+
+ // any user with read access to the unrestricted list can see details but no links to the linked restricted issues
+ impersonate(FOLDER_ADMIN.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(UNRESTRICTED_ISSUES_LIST));
+ verifyRelatedIssueAccess(ISSUE_3, ISSUE_1, false);
+ verifyRelatedIssueAccess(ISSUE_3, ISSUE_2, false);
+ stopImpersonating();
+
+ // users can link to the restricted issues they have access to
+ impersonate(USER1.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(UNRESTRICTED_ISSUES_LIST));
+ verifyRelatedIssueAccess(ISSUE_3, ISSUE_1, true);
+ verifyRelatedIssueAccess(ISSUE_3, ISSUE_2, false);
+ stopImpersonating();
+
+ impersonate(USER2.getEmail());
+ goToProjectHome();
+ clickAndWait(Locator.linkContainingText(UNRESTRICTED_ISSUES_LIST));
+ verifyRelatedIssueAccess(ISSUE_3, ISSUE_1, false);
+ verifyRelatedIssueAccess(ISSUE_3, ISSUE_2, true);
+ stopImpersonating();
+ }
+
+ private void verifyRelatedIssueAccess(String issueID, String relatedIssueID, boolean shouldHaveRelatedAccess)
+ {
+ Locator issueLink = getIssueLinkLocator(issueID);
+ waitForElement(issueLink, defaultWaitForPage);
+ pushLocation();
+ clickAndWait(issueLink);
+ Locator relatedIssueLink = getIssueLinkLocator(relatedIssueID);
+ if (shouldHaveRelatedAccess)
+ {
+ assertElementPresent(relatedIssueLink);
+ // related link should also navigate properly
+ clickAndWait(relatedIssueLink);
+ assertTextNotPresent(ACCESS_ERROR_MSG);
+ }
+ else
+ {
+ // no link but the related ID should render as text
+ assertElementNotPresent(relatedIssueLink);
+ assertTextPresent(relatedIssueID);
+ }
+ popLocation();
+ }
+
+ private Locator getIssueLinkLocator(String issueID)
+ {
+ return Locator.tagWithAttributeContaining("a", "href", String.format("issues-details.view?issueId=%s", issueID));
+ }
+}
diff --git a/sla/resources/queries/sla/ProtocolProjectsUsage.sql b/sla/resources/queries/sla/ProtocolProjectsUsage.sql
index 15e6336d1..f169ef15f 100644
--- a/sla/resources/queries/sla/ProtocolProjectsUsage.sql
+++ b/sla/resources/queries/sla/ProtocolProjectsUsage.sql
@@ -13,7 +13,7 @@ SELECT
y.grantNumber as OGAGrantNumber,
y.fiscalAuthorityName As FiscalAuthorityName,
aa.Species,
- aa.Gender as Sex,
+ aa.Gender,
aa.Strain,
aa.Allowed AS NumAllowed,
calc.NumUsed,