diff --git a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/completionDates/.qview.xml b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/completionDates/.qview.xml index 0a2d166f1..98bc8263f 100644 --- a/EHR_ComplianceDB/resources/queries/ehr_compliancedb/completionDates/.qview.xml +++ b/EHR_ComplianceDB/resources/queries/ehr_compliancedb/completionDates/.qview.xml @@ -22,6 +22,7 @@ + diff --git a/EHR_ComplianceDB/resources/schemas/dbscripts/postgresql/EHR_ComplianceDB-12.38-12.39.sql b/EHR_ComplianceDB/resources/schemas/dbscripts/postgresql/EHR_ComplianceDB-12.38-12.39.sql new file mode 100644 index 000000000..230b83b76 --- /dev/null +++ b/EHR_ComplianceDB/resources/schemas/dbscripts/postgresql/EHR_ComplianceDB-12.38-12.39.sql @@ -0,0 +1 @@ +ALTER TABLE ehr_compliancedb.CompletionDates ADD COLUMN FileName varchar(500); \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/schemas/dbscripts/postgresql/EHR_ComplianceDB-12.39-12.40.sql b/EHR_ComplianceDB/resources/schemas/dbscripts/postgresql/EHR_ComplianceDB-12.39-12.40.sql new file mode 100644 index 000000000..2ee05593c --- /dev/null +++ b/EHR_ComplianceDB/resources/schemas/dbscripts/postgresql/EHR_ComplianceDB-12.39-12.40.sql @@ -0,0 +1 @@ +ALTER TABLE ehr_compliancedb.Employees ALTER COLUMN Notes TYPE VARCHAR (4000); \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/EHR_ComplianceDB-12.38-12.39.sql b/EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/EHR_ComplianceDB-12.38-12.39.sql new file mode 100644 index 000000000..ca7d99334 --- /dev/null +++ b/EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/EHR_ComplianceDB-12.38-12.39.sql @@ -0,0 +1 @@ +ALTER TABLE ehr_compliancedb.CompletionDates ADD FileName nvarchar(500); \ No newline at end of file diff --git a/EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/EHR_ComplianceDB-12.39-12.40.sql b/EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/EHR_ComplianceDB-12.39-12.40.sql new file mode 100644 index 000000000..088f94886 --- /dev/null +++ b/EHR_ComplianceDB/resources/schemas/dbscripts/sqlserver/EHR_ComplianceDB-12.39-12.40.sql @@ -0,0 +1,2 @@ +ALTER TABLE ehr_compliancedb.Employees ALTER COLUMN Notes NVARCHAR (4000); + diff --git a/EHR_ComplianceDB/resources/schemas/ehr_compliancedb.xml b/EHR_ComplianceDB/resources/schemas/ehr_compliancedb.xml index 987fd4062..a2f83fe82 100644 --- a/EHR_ComplianceDB/resources/schemas/ehr_compliancedb.xml +++ b/EHR_ComplianceDB/resources/schemas/ehr_compliancedb.xml @@ -93,18 +93,15 @@ Last Name - 100 ALWAYS_OFF true First Name - 100 ALWAYS_OFF Middle Name - 100 ALWAYS_OFF @@ -201,10 +198,12 @@ true Start Date + Date true End Date + Date true @@ -511,6 +510,7 @@ false Date Completed + Date true @@ -529,6 +529,10 @@ true Comment + + FileName + false + false true @@ -709,6 +713,7 @@ true Date Completed + Date false diff --git a/EHR_ComplianceDB/resources/views/publicPage.html b/EHR_ComplianceDB/resources/views/publicPage.html index 2cd3b1402..92ff487de 100644 --- a/EHR_ComplianceDB/resources/views/publicPage.html +++ b/EHR_ComplianceDB/resources/views/publicPage.html @@ -19,7 +19,13 @@ xtype: 'ldk-linkbutton', text: '
  • View Employee List
  • ', href: LABKEY.ActionURL.buildURL('query', 'executeQuery', null, {schemaName: 'EmployeeData', 'query.queryName': 'Employees'}) - },{ + }, +// { +// xtype: 'ldk-linkbutton', +// text: '
  • View Respirator Protection Quarantine Report
  • ', +// href: LABKEY.ActionURL.buildURL('query', 'executeQuery', null, {schemaName: 'EmployeeData', 'query.queryName': 'RespiratorProtectionQuarantine'}) +// }, + { xtype: 'ldk-linkbutton', text: '
  • View Private Section (authorized users only)
  • ', href: LABKEY.ActionURL.buildURL('project', 'start', container), diff --git a/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceDBModule.java b/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceDBModule.java index 766116000..ed0734f0c 100644 --- a/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceDBModule.java +++ b/EHR_ComplianceDB/src/org/labkey/ehr_compliancedb/EHR_ComplianceDBModule.java @@ -49,7 +49,7 @@ public String getName() @Override public @Nullable Double getSchemaVersion() { - return 12.38; + return 12.40; } @Override diff --git a/ehr/api-src/org/labkey/api/ehr/EHRService.java b/ehr/api-src/org/labkey/api/ehr/EHRService.java index 923215310..9f3d998bc 100644 --- a/ehr/api-src/org/labkey/api/ehr/EHRService.java +++ b/ehr/api-src/org/labkey/api/ehr/EHRService.java @@ -19,6 +19,8 @@ import org.jetbrains.annotations.Nullable; import org.labkey.api.data.AbstractTableInfo; import org.labkey.api.data.Container; +import org.labkey.api.data.CoreSchema; +import org.labkey.api.data.SQLFragment; import org.labkey.api.data.TableCustomizer; import org.labkey.api.data.TableInfo; import org.labkey.api.ehr.dataentry.DataEntryForm; @@ -26,12 +28,12 @@ import org.labkey.api.ehr.dataentry.SingleQueryFormProvider; import org.labkey.api.ehr.demographics.DemographicsProvider; import org.labkey.api.ehr.demographics.ProjectValidator; -import org.labkey.api.ehr.history.HistoryDataSource; -import org.labkey.api.ehr.history.LabworkType; +import org.labkey.api.ehr.history.*; import org.labkey.api.ldk.table.ButtonConfigFactory; import org.labkey.api.module.Module; import org.labkey.api.query.BatchValidationException; import org.labkey.api.query.DetailsURL; +import org.labkey.api.query.ExprColumn; import org.labkey.api.query.FieldKey; import org.labkey.api.resource.Resource; import org.labkey.api.security.User; @@ -126,6 +128,32 @@ static public void setInstance(EHRService instance) /** @return the project validator set by the EHR module, note a center specific module may have overridden the default */ abstract public ProjectValidator getProjectValidator(); + public enum EndingOption + { + /** end date is not set, or any day in the future */ + activeAfterMidnightTonight(new SQLFragment(" WHEN (CAST(" + ExprColumn.STR_TABLE_ALIAS + ".enddate AS DATE) > {fn curdate()}) THEN " + CoreSchema.getInstance().getSchema().getSqlDialect().getBooleanTRUE())), + /** ends anytime today */ + endsToday(new SQLFragment("WHEN (" + ExprColumn.STR_TABLE_ALIAS + ".enddate IS NOT NULL AND CAST(" + ExprColumn.STR_TABLE_ALIAS + ".enddate AS DATE) = {fn curdate()}) THEN " + CoreSchema.getInstance().getSchema().getSqlDialect().getBooleanTRUE())), + /** consider records that start/stop on today's date to be active */ + allowSameDay(new SQLFragment(" WHEN (" + ExprColumn.STR_TABLE_ALIAS + ".enddate IS NOT NULL AND CAST(" + ExprColumn.STR_TABLE_ALIAS + ".enddate AS DATE) = {fn curdate()} AND CAST(" + ExprColumn.STR_TABLE_ALIAS + ".date as DATE) = {fn curdate()}) THEN " + CoreSchema.getInstance().getSchema().getSqlDialect().getBooleanTRUE())), + /** end time must be before right now */ + endingBeforeNow(new SQLFragment(" WHEN (" + ExprColumn.STR_TABLE_ALIAS + ".enddate >= {fn now()}) THEN " + CoreSchema.getInstance().getSchema().getSqlDialect().getBooleanTRUE())); + + private final SQLFragment _sql; + + EndingOption(SQLFragment sql) + { + _sql = sql; + } + + public SQLFragment getSql() + { + return _sql; + } + } + + public abstract void addIsActiveCol(AbstractTableInfo ti, boolean includeExpired, EndingOption... endOptions); + /** Categories where pre-configured reports can be offered to the user */ public enum REPORT_LINK_TYPE { diff --git a/ehr/api-src/org/labkey/api/ehr/history/DefaultLabworkType.java b/ehr/api-src/org/labkey/api/ehr/history/DefaultLabworkType.java index e24718f24..af79e3021 100644 --- a/ehr/api-src/org/labkey/api/ehr/history/DefaultLabworkType.java +++ b/ehr/api-src/org/labkey/api/ehr/history/DefaultLabworkType.java @@ -230,6 +230,10 @@ protected String getLine(Results rs, boolean redacted) throws SQLException StringBuilder sb = new StringBuilder(); String testId = getTestId(rs); Double result = _resultField == null ? null : rs.getDouble(FieldKey.fromString(_resultField)); + if (rs.wasNull()) + { + result = null; + } String units = _unitsField == null ? null : rs.getString(FieldKey.fromString(_unitsField)); String qualResult = _qualResultField == null ? null : rs.getString(FieldKey.fromString(_qualResultField)); diff --git a/ehr/api-src/org/labkey/api/ehr/history/LabworkType.java b/ehr/api-src/org/labkey/api/ehr/history/LabworkType.java index 0ab6413d9..f864cd3aa 100644 --- a/ehr/api-src/org/labkey/api/ehr/history/LabworkType.java +++ b/ehr/api-src/org/labkey/api/ehr/history/LabworkType.java @@ -39,4 +39,9 @@ public interface LabworkType Map> getResults(Container c, User u, List runIds, boolean redacted); Map> getResults(Container c, User u, String id, Date minDate, Date maxDate, boolean redacted); + + default boolean showPerformedBy() + { + return true; + } } diff --git a/ehr/api-src/org/labkey/api/ehr/table/DurationColumn.java b/ehr/api-src/org/labkey/api/ehr/table/DurationColumn.java index 0d27ffc05..44bad57c3 100644 --- a/ehr/api-src/org/labkey/api/ehr/table/DurationColumn.java +++ b/ehr/api-src/org/labkey/api/ehr/table/DurationColumn.java @@ -17,6 +17,7 @@ import org.apache.commons.lang3.time.DurationFormatUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.labkey.api.data.ColumnInfo; import org.labkey.api.data.DataColumn; import org.labkey.api.data.RenderContext; @@ -32,9 +33,11 @@ public class DurationColumn extends DataColumn { - String _startDateColumn; - String _endDateColumn; - private String _durationFormat; + protected final String _startDateColumn; + protected final String _endDateColumn; + private final String _durationFormat; + + private boolean _dropTime; public DurationColumn(ColumnInfo col, String startDateColumn, String endDateColumn) { @@ -49,6 +52,12 @@ public DurationColumn(ColumnInfo col, String startDateColumn, String endDateColu _durationFormat = durationFormat; } + /** Treat all times as if they were at midnight of the same day */ + public void setDropTime(boolean dropTime) + { + _dropTime = dropTime; + } + @Override public Class getDisplayValueClass() { @@ -60,12 +69,24 @@ public Class getDisplayValueClass() @Override public Object getDisplayValue(RenderContext ctx) { - return getFormattedDuration((Date)ctx.get(getMappedFieldKey(_startDateColumn)), (Date)ctx.get(getMappedFieldKey(_endDateColumn))); + Date startDate = (Date)ctx.get(getMappedFieldKey(_startDateColumn)); + Date endDate = (Date)ctx.get(getMappedFieldKey(_endDateColumn)); + + return getFormattedDuration(startDate, endDate); + } + + private void dropTime(@NotNull Calendar cal) + { + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); } - protected String getFormattedDuration(Date startDate, Date endDate) + /** Convert from dates to calendars, dealing with nulls */ + public final String getFormattedDuration(@Nullable Date startDate, @Nullable Date endDate) { - if (startDate == null || _durationFormat == null) + if (startDate == null) return null; Calendar startCal = Calendar.getInstance(); @@ -74,6 +95,20 @@ protected String getFormattedDuration(Date startDate, Date endDate) Calendar endCal = Calendar.getInstance(); endCal.setTime(endDate == null ? new Date() : endDate); + if (_dropTime) + { + // Snap to midnight so that days work based on calendar day instead of 24-hour periods + dropTime(startCal); + dropTime(endCal); + } + return getFormattedDuration(startCal, endCal); + } + + protected String getFormattedDuration(@NotNull Calendar startCal, @NotNull Calendar endCal) + { + if (_durationFormat == null) + return null; + String formattedDuration; try { @@ -113,24 +148,4 @@ protected FieldKey getMappedFieldKey(String colName) { return new FieldKey(getBoundColumn().getFieldKey().getParent(), colName); } - - public String getStartDateColumn() - { - return _startDateColumn; - } - - public void setStartDateColumn(String startDateColumn) - { - _startDateColumn = startDateColumn; - } - - public String getEndDateColumn() - { - return _endDateColumn; - } - - public void setEndDateColumn(String endDateColumn) - { - _endDateColumn = endDateColumn; - } } diff --git a/ehr/resources/queries/study/treatment_order.query.xml b/ehr/resources/queries/study/treatment_order.query.xml index c2f6f03a3..9dab559d4 100644 --- a/ehr/resources/queries/study/treatment_order.query.xml +++ b/ehr/resources/queries/study/treatment_order.query.xml @@ -62,6 +62,11 @@ ehr_lookups treatment_frequency rowid + + + + +
    diff --git a/ehr/resources/reports/schemas/study/Pedigree/Pedigree.r b/ehr/resources/reports/schemas/study/Pedigree/Pedigree.r index bda5bf9a1..5b51f09ce 100644 --- a/ehr/resources/reports/schemas/study/Pedigree/Pedigree.r +++ b/ehr/resources/reports/schemas/study/Pedigree/Pedigree.r @@ -13,10 +13,10 @@ library(Rlabkey) #str(labkey.data); #warnings(); -labkey.acceptSelfSignedCerts(); +labkey.setCurlOptions(ssl_verifypeer = FALSE, ssl_verifyhost = FALSE) -if ((length(labkey.data$id) == 0) | (is.na(labkey.data$dam) & is.na(labkey.data$sire))){ +if ((length(labkey.data$id) == 0) || all(is.na(labkey.data$dam) & is.na(labkey.data$sire))) { png(filename="${imgout:myscatterplot}", width = 650, height = 150); plot(0, 0, type='n', xaxt='n', yaxt='n', bty='n', ann=FALSE ) title(main = "No pedigree data found for selected animal(s).", sub = NULL, xlab = NULL, ylab = NULL, @@ -200,8 +200,8 @@ if ((length(labkey.data$id) == 0) | (is.na(labkey.data$dam) & is.na(labkey.data$ if (length(damIndex) == 0) damIndex <- which(allPed$Id == ped$Dam[i]); if (length(sireIndex) == 0) sireIndex <- which(allPed$Id == ped$Sire[i]); - if((is.na(ped$Sire[i]))& (!is.na(ped$Dam[i]))){ - xt <- sample (1:30,1) + if(is.na(ped$Sire[i])){ + xt <- sample (1:99,1) #typeof(ped$Sire); #typeof(xt); ped$Sire[i] <- paste('xxs',xt) @@ -209,8 +209,8 @@ if ((length(labkey.data$id) == 0) | (is.na(labkey.data$dam) & is.na(labkey.data$ #print(ped$Dam[i]) #print(ped$Sire[i]) } - if((is.na(ped$Dam[i]))& (!is.na(ped$Sire[i]))){ - xt <- sample (1:30,1) + if(is.na(ped$Dam[i])){ + xt <- sample (1:99,1) #typeof(ped$Sire); #typeof(xt); ped$Dam[i] <- paste ('xxd',xt); diff --git a/ehr/resources/schemas/ehr_lookups.xml b/ehr/resources/schemas/ehr_lookups.xml index daac2f84d..a4cfb2288 100644 --- a/ehr/resources/schemas/ehr_lookups.xml +++ b/ehr/resources/schemas/ehr_lookups.xml @@ -2637,7 +2637,9 @@ entityid - + + Date Disabled + diff --git a/ehr/resources/views/groupOverlaps.html b/ehr/resources/views/groupOverlaps.html index cf8e4bcb3..f3c8a9515 100644 --- a/ehr/resources/views/groupOverlaps.html +++ b/ehr/resources/views/groupOverlaps.html @@ -162,8 +162,11 @@ return; } + // By Kollil, 3/22/2018 : In 17.2 the filter is not working. Removed the the line 168 and added the filterArray at line 169. + // The Animal group search is working fine now after this change. if (groupName) - config.removeableFilters = [LABKEY.Filter.create('groupId/name', groupName, LABKEY.Filter.Types.EQUAL)]; + //config.removeableFilters = [LABKEY.Filter.create('groupId/name', groupName, LABKEY.Filter.Types.EQUAL)]; + config.filterArray = [LABKEY.Filter.create('groupId/name', groupName, LABKEY.Filter.Types.EQUAL)]; var params = { StartDate: start, @@ -172,7 +175,8 @@ config.parameters = params; - LDK.Utils.getReadOnlyQWP(config).render(this.qwpDiv.id); + LDK.Utils.getReadOnlyQWP(config); + } }); diff --git a/ehr/resources/views/housingOverlaps.html b/ehr/resources/views/housingOverlaps.html index 4122230f2..bb691f629 100644 --- a/ehr/resources/views/housingOverlaps.html +++ b/ehr/resources/views/housingOverlaps.html @@ -200,7 +200,7 @@ if (!LABKEY.Utils.isEmptyObj(params)) config.parameters = params; - LDK.Utils.getReadOnlyQWP(config).render(this.qwpDiv.id); + LDK.Utils.getReadOnlyQWP(config); } }).render(webpart.wrapperDivId); diff --git a/ehr/resources/web/ehr/DataEntryUtils.js b/ehr/resources/web/ehr/DataEntryUtils.js index d838a6473..531683cb1 100644 --- a/ehr/resources/web/ehr/DataEntryUtils.js +++ b/ehr/resources/web/ehr/DataEntryUtils.js @@ -823,29 +823,6 @@ EHR.DataEntryUtils = new function(){ return EHR._projectStore; }, - getProjectCodeStore: function(){ - //TODO: this really belongs in CNPRC_EHR module, not here. - if (EHR._projectStore) - return EHR._projectStore; - - var storeId = ['cnprc_ehr', 'project', 'projectCode'].join('||'); - - var ctx = EHR.Utils.getEHRContext(); - - EHR._projectStore = Ext4.StoreMgr.get(storeId) || new LABKEY.ext4.data.Store({ - type: 'labkey-store', - containerPath: ctx ? ctx['EHRStudyContainer'] : null, - schemaName: 'cnprc_ehr', - queryName: 'project', - columns: 'projectCode', - //filterArray: [LABKEY.Filter.create('enddate', null, LABKEY.Filter.Types.ISBLANK)], - sort: 'projectCode', - storeId: storeId, - autoLoad: true - }); - - return EHR._projectStore; - }, getDefaultClinicalProject: function(){ var ctx = EHR.Utils.getEHRContext(); @@ -908,9 +885,16 @@ EHR.DataEntryUtils = new function(){ calculateDrugVolume: function(valMap, rounding, fixedAmount){ var vol; if (!fixedAmount){ - // vol = dosage * weight / conc (ie. mg/kg * kg / mg/ml) if (valMap.concentration && valMap.dosage && valMap.weight){ - vol = valMap.dosage * valMap.weight / valMap.concentration; + if (valMap.dosage_units === 'ml/kg') { + // Some drugs are in ml/kg instead of mg/kg. In those cases, concentration is irrelevant. + vol = valMap.dosage * valMap.weight; + + } + else { + // vol = dosage * weight / conc (ie. mg/kg * kg / mg/ml) + vol = valMap.dosage * valMap.weight / valMap.concentration; + } } } else { diff --git a/ehr/resources/web/ehr/data/ClinpathRunsClientStore.js b/ehr/resources/web/ehr/data/ClinpathRunsClientStore.js index af881f471..d0eaa2858 100644 --- a/ehr/resources/web/ehr/data/ClinpathRunsClientStore.js +++ b/ehr/resources/web/ehr/data/ClinpathRunsClientStore.js @@ -32,19 +32,10 @@ Ext4.define('EHR.data.ClinpathRunsClientStore', { }, onRecordUpdate: function(record, modifiedFieldNames){ + var store = EHR.DataEntryUtils.getLabworkServicesStore(); if (record.get('servicerequested')){ modifiedFieldNames = modifiedFieldNames || []; - var storeId = LABKEY.ext4.Util.getLookupStoreId({ - lookup: { - schemaName: 'ehr_lookups', - queryName: 'labwork_services', - keyColumn: 'servicename', - displayColumn: 'servicename' - } - }); - - var store = Ext4.StoreMgr.get(storeId); if (!store){ LDK.Utils.logToServer({ message: 'Unable to find lookup store in ClinpathRunsClientStore' diff --git a/ehr/resources/web/ehr/data/DataEntryServerStore.js b/ehr/resources/web/ehr/data/DataEntryServerStore.js index dd94b72c4..e77ed8242 100644 --- a/ehr/resources/web/ehr/data/DataEntryServerStore.js +++ b/ehr/resources/web/ehr/data/DataEntryServerStore.js @@ -552,16 +552,24 @@ Ext4.define('EHR.data.DataEntryServerStore', { //transfer values var clientVal = Ext4.isEmpty(clientModel.get(clientFieldName)) ? null : clientModel.get(clientFieldName); var serverVal = Ext4.isEmpty(serverModel.get(serverFieldName)) ? null : serverModel.get(serverFieldName); - if (serverVal != clientVal){ - changedData = true; + + // See if the server and client disagree on the values at this point + var needToSetModel = serverVal !== clientVal; + // The client may already match if its value happens to be set by getInitialValue() and + // we're loading an existing record. If so, we still may need to push it into the raw part + // of the record + var needToSetRawModel = clientModel.raw && (needToSetModel || !clientModel.raw[clientFieldName]); + + if (needToSetModel){ + changedData = true; clientModel.set(clientFieldName, serverVal); - if (serverModel.raw && serverModel.raw[serverFieldName]){ - clientModel.raw[clientFieldName] = clientModel.raw[clientFieldName] || {}; - Ext4.apply(clientModel.raw[clientFieldName], serverModel.raw[serverFieldName]); - delete clientModel.raw[clientFieldName].url; - } changedStoreIDs[clientStore.storeId] = true; } + if (needToSetRawModel && serverModel.raw && serverModel.raw[serverFieldName]){ + clientModel.raw[clientFieldName] = clientModel.raw[clientFieldName] || {}; + Ext4.apply(clientModel.raw[clientFieldName], serverModel.raw[serverFieldName]); + delete clientModel.raw[clientFieldName].url; + } } //also sync server errors diff --git a/ehr/resources/web/ehr/form/field/SnomedCodesEditor.js b/ehr/resources/web/ehr/form/field/SnomedCodesEditor.js index eb4561516..a5c336754 100644 --- a/ehr/resources/web/ehr/form/field/SnomedCodesEditor.js +++ b/ehr/resources/web/ehr/form/field/SnomedCodesEditor.js @@ -174,7 +174,7 @@ Ext4.define('EHR.window.SnomedCodeWindow', { items: [{ xtype: 'button', style: 'margin-right: 5px;', - width: 20, + width: 28, testLocator: 'snomedUpArrow', icon: LABKEY.ActionURL.getContextPath() + '/_images/uparrow.gif', //text: 'Up', @@ -195,7 +195,7 @@ Ext4.define('EHR.window.SnomedCodeWindow', { },{ xtype: 'button', style: 'margin-right: 5px;', - width: 20, + width: 28, testLocator: 'snomedDownArrow', icon: LABKEY.ActionURL.getContextPath() + '/_images/downarrow.gif', handler: function(btn){ @@ -215,7 +215,7 @@ Ext4.define('EHR.window.SnomedCodeWindow', { },{ xtype: 'button', style: 'margin-right: 5px;', - width: 20, + width: 28, testLocator: 'snomedDelete', icon: LABKEY.ActionURL.getContextPath() + '/_images/delete.gif', handler: function(btn){ diff --git a/ehr/resources/web/ehr/grid/Panel.js b/ehr/resources/web/ehr/grid/Panel.js index 0b43418f7..b1341ff56 100644 --- a/ehr/resources/web/ehr/grid/Panel.js +++ b/ehr/resources/web/ehr/grid/Panel.js @@ -20,6 +20,19 @@ Ext4.define('EHR.grid.Panel', { this.configureColumns(); this.sortColumns(); + var dockedItems = [{ + xtype: 'toolbar', + dock: 'top', + items: this.getTbarButtons() + }]; + if (this.formConfig.topAndBottomButtons) { + dockedItems.push({ + xtype: 'toolbar', + dock: 'bottom', + items: this.getTbarButtons() + }) + } + Ext4.apply(this, { cls: 'ldk-grid', clicksToEdit: 1, @@ -29,11 +42,7 @@ Ext4.define('EHR.grid.Panel', { defaults: { border: false }, - dockedItems: [{ - xtype: 'toolbar', - dock: 'top', - items: this.getTbarButtons() - }] + dockedItems: dockedItems }); if (this.allowDragDropReorder) { @@ -335,4 +344,4 @@ Ext4.define('EHR.grid.Panel', { return buttons; } -}); \ No newline at end of file +}); diff --git a/ehr/resources/web/ehr/model/sources/Default.js b/ehr/resources/web/ehr/model/sources/Default.js index 0e23bcfc3..a56d8549c 100644 --- a/ehr/resources/web/ehr/model/sources/Default.js +++ b/ehr/resources/web/ehr/model/sources/Default.js @@ -655,6 +655,24 @@ EHR.model.DataModelManager.registerMetadata('Default', { columnConfig: { width: 160 } + }, + QCState: { + getInitialValue: function(v){ + var qc; + if (!v && EHR.Security.getQCStateByLabel('Completed')) + qc = EHR.Security.getQCStateByLabel('Completed').RowId; + return v || qc; + } + } + }, + 'study.geneticAncestry': { + QCState: { + getInitialValue: function(v){ + var qc; + if (!v && EHR.Security.getQCStateByLabel('Completed')) + qc = EHR.Security.getQCStateByLabel('Completed').RowId; + return v || qc; + } } }, 'study.Demographics': { @@ -2631,9 +2649,11 @@ EHR.model.DataModelManager.registerMetadata('Default', { } }, 'ehr_lookups.drug_defaults': { - editorConfig: { - xtype: 'ehr-snomedcombo', - defaultSubset: 'All' + code: { + editorConfig: { + xtype: 'ehr-snomedcombo', + defaultSubset: 'All' + } }, category: { defaultValue: 'Standard' diff --git a/ehr/resources/web/ehr/panel/AnimalGroupDetailsPanel.js b/ehr/resources/web/ehr/panel/AnimalGroupDetailsPanel.js index aad62e9d0..100bf018c 100644 --- a/ehr/resources/web/ehr/panel/AnimalGroupDetailsPanel.js +++ b/ehr/resources/web/ehr/panel/AnimalGroupDetailsPanel.js @@ -70,7 +70,7 @@ Ext4.define('EHR.panel.AnimalGroupDetailsPanel', { value: this.groupRow.getDisplayValue('purpose') },{ fieldLabel: 'Comments', - value: this.groupRow.getDisplayValue('comments') + value: this.groupRow.getDisplayValue('comment') }] }] }); diff --git a/ehr/resources/web/ehr/panel/BulkEditPanel.js b/ehr/resources/web/ehr/panel/BulkEditPanel.js index 03dc074d8..bb3af96a4 100644 --- a/ehr/resources/web/ehr/panel/BulkEditPanel.js +++ b/ehr/resources/web/ehr/panel/BulkEditPanel.js @@ -38,6 +38,7 @@ Ext4.define('EHR.panel.BulkEditPanel', { formConfig: this.formConfig, store: this.getStoreCopy(), textareaFieldWidth: EHR.form.Panel.defaultFieldWidth, + maxFieldWidth: EHR.form.Panel.defaultFieldWidth, bindConfig: { createRecordOnLoad: true } diff --git a/ehr/resources/web/ehr/panel/ClinicalManagementPanel.js b/ehr/resources/web/ehr/panel/ClinicalManagementPanel.js index 881c718be..e2f5d03b5 100644 --- a/ehr/resources/web/ehr/panel/ClinicalManagementPanel.js +++ b/ehr/resources/web/ehr/panel/ClinicalManagementPanel.js @@ -270,7 +270,8 @@ Ext4.define('EHR.panel.ClinicalManagementPanel', { menu.floating = true; var owner = Ext4.create('Ext.panel.Panel', { - border: false + border: false, + width: 0 }); owner.render(el); menu.setFloatParent(owner); diff --git a/ehr/resources/web/ehr/panel/HousingDataEntryPanel.js b/ehr/resources/web/ehr/panel/HousingDataEntryPanel.js index d9c9a8eb2..9c848e11d 100644 --- a/ehr/resources/web/ehr/panel/HousingDataEntryPanel.js +++ b/ehr/resources/web/ehr/panel/HousingDataEntryPanel.js @@ -17,7 +17,7 @@ Ext4.define('EHR.panel.HousingDataEntryPanel', { LDK.Assert.assertNotEmpty('Unable to find housing store in HousingDataEntryPanel', store); if (extraContext && extraContext.successURL && store.getCount() > 0){ - Ext4.Msg.confirm('Success', 'Do you want to view to room layout now? This will allow you to verify and/or change dividers', function(val){ + Ext4.Msg.confirm('Success', 'Do you want to view the room layout now? This will allow you to verify and/or change dividers', function(val){ window.onbeforeunload = Ext4.emptyFn; if (val == 'yes'){ diff --git a/ehr/resources/web/ehr/panel/ManageTreatmentsPanel.js b/ehr/resources/web/ehr/panel/ManageTreatmentsPanel.js index f1b53e302..8e9e147c0 100644 --- a/ehr/resources/web/ehr/panel/ManageTreatmentsPanel.js +++ b/ehr/resources/web/ehr/panel/ManageTreatmentsPanel.js @@ -86,6 +86,15 @@ Ext4.define('EHR.panel.ManageTreatmentsPanel', { defaultValue: animalId, editable: false }, + //Added: 7-10-2019 R.Blasa + frequency: { + allowBlank: false, + lookup: { + sort: 'sort_order', + filterArray: [LABKEY.Filter.create('active', true, LABKEY.Filter.Types.EQUAL)], + columns: '*' + } + }, category: { defaultValue: category } diff --git a/ehr/resources/web/ehr/plugin/RowEditor.js b/ehr/resources/web/ehr/plugin/RowEditor.js index d8977d5a2..6e3eccc21 100644 --- a/ehr/resources/web/ehr/plugin/RowEditor.js +++ b/ehr/resources/web/ehr/plugin/RowEditor.js @@ -104,7 +104,7 @@ Ext4.define('EHR.plugin.RowEditor', { if (cols > 1){ var newWidth = cols * (EHR.form.Panel.defaultFieldWidth + 20); if (newWidth > win.width) { - win.setWidth(); + win.setWidth(newWidth); } } }, diff --git a/ehr/resources/web/ehr/utils.js b/ehr/resources/web/ehr/utils.js index e50ac56d8..24227b8af 100644 --- a/ehr/resources/web/ehr/utils.js +++ b/ehr/resources/web/ehr/utils.js @@ -529,8 +529,8 @@ EHR.Utils = new function(){ } //append non-removeable filters - if (LABKEY.DataRegions[dataRegionName].getBaseFilters().length){ - var array = LABKEY.DataRegions[dataRegionName].getBaseFilters(); + if (LABKEY.DataRegions[dataRegionName].filters && LABKEY.DataRegions[dataRegionName].filters){ + var array = LABKEY.DataRegions[dataRegionName].filters; for (var i=0;i 1){ - win.setWidth(cols * (EHR.form.Panel.defaultFieldWidth + 20)); + win.setWidth(cols * (EHR.form.Panel.defaultFieldWidth + 30)); } } } diff --git a/ehr/resources/web/ehr/window/CreateTaskFromIdsWindow.js b/ehr/resources/web/ehr/window/CreateTaskFromIdsWindow.js index fba24f302..d39246e7e 100644 --- a/ehr/resources/web/ehr/window/CreateTaskFromIdsWindow.js +++ b/ehr/resources/web/ehr/window/CreateTaskFromIdsWindow.js @@ -234,7 +234,7 @@ Ext4.define('EHR.window.CreateTaskFromIdsWindow', { var type = this.down('#type').getValue().type; if (type == 'createNew'){ return { - date: this.down('#date').getValue(), + duedate: this.down('#date').getValue(), assignedTo: this.down('#assignedTo').getValue(), title: this.down('#titleField').getValue(), category: 'task', @@ -307,4 +307,4 @@ Ext4.define('EHR.window.CreateTaskFromIdsWindow', { failure: LDK.Utils.getErrorCallback() }); } -}); \ No newline at end of file +}); diff --git a/ehr/resources/web/ehr/window/CreateTaskFromRecordsWindow.js b/ehr/resources/web/ehr/window/CreateTaskFromRecordsWindow.js index 85b2527ed..0abb1da7a 100644 --- a/ehr/resources/web/ehr/window/CreateTaskFromRecordsWindow.js +++ b/ehr/resources/web/ehr/window/CreateTaskFromRecordsWindow.js @@ -346,7 +346,7 @@ Ext4.define('EHR.window.CreateTaskFromRecordsWindow', { EHR.Utils.createTask({ initialQCState: 'Scheduled', existingRecords: existingRecords, - taskRecord: {date: date, assignedTo: assignedTo, category: 'task', title: title, formType: this.formType}, + taskRecord: {duedate: date, assignedTo: assignedTo, category: 'task', title: title, formType: this.formType}, scope: this, success: this.createTaskSuccess, failure: LDK.Utils.getErrorCallback() @@ -391,4 +391,4 @@ Ext4.define('EHR.window.CreateTaskFromRecordsWindow', { dataRegion.refresh(); this.close(); } -}); \ No newline at end of file +}); diff --git a/ehr/resources/web/ehr/window/EncounterAddRecordWindow.js b/ehr/resources/web/ehr/window/EncounterAddRecordWindow.js index b61a93dff..c6c52090a 100644 --- a/ehr/resources/web/ehr/window/EncounterAddRecordWindow.js +++ b/ehr/resources/web/ehr/window/EncounterAddRecordWindow.js @@ -139,4 +139,4 @@ EHR.DataEntryUtils.registerGridButton('ENCOUNTERADD', function(config){ }).show(); } }, config); -}); \ No newline at end of file +}); diff --git a/ehr/src/org/labkey/ehr/EHRController.java b/ehr/src/org/labkey/ehr/EHRController.java index 22a49b5fd..3d537fb5d 100644 --- a/ehr/src/org/labkey/ehr/EHRController.java +++ b/ehr/src/org/labkey/ehr/EHRController.java @@ -1447,7 +1447,7 @@ public ModelAndView getView(EnterDataForm form, BindException errors) } _title = _def.getLabel(); - + getPageConfig().setIncludePostParameters(true); return _def.createView(); } diff --git a/ehr/src/org/labkey/ehr/EHRModule.java b/ehr/src/org/labkey/ehr/EHRModule.java index 9d6a63832..d3c90ea2d 100644 --- a/ehr/src/org/labkey/ehr/EHRModule.java +++ b/ehr/src/org/labkey/ehr/EHRModule.java @@ -256,6 +256,8 @@ public void moduleStartupComplete(ServletContext servletContext) EHRService.get().registerMoreActionsButton(new MarkCompletedButton(this, "study", "parentage", "End Selected Calls", true), "study", "parentage"); EHRService.get().registerMoreActionsButton(new ExcelImportButton(this, "study", "parentage", "Import Data"), "study", "parentage"); + EHRService.get().registerMoreActionsButton(new ExcelImportButton(this, "study", "geneticAncestry", "Import Data"), "study", "geneticAncestry"); + EHRService.get().registerMoreActionsButton(new ProtocolEditButton(this, "ehr", "protocol"), "ehr", "protocol"); EHRService.get().registerMoreActionsButton(new ProtocolEditButton(this, "ehr", "protocol_amendments"), "ehr", "protocol_amendments"); EHRService.get().registerMoreActionsButton(new ProtocolEditButton(this, "ehr", "protocol_counts"), "ehr", "protocol_counts"); diff --git a/ehr/src/org/labkey/ehr/EHRServiceImpl.java b/ehr/src/org/labkey/ehr/EHRServiceImpl.java index be783b506..687a569fb 100644 --- a/ehr/src/org/labkey/ehr/EHRServiceImpl.java +++ b/ehr/src/org/labkey/ehr/EHRServiceImpl.java @@ -443,7 +443,6 @@ public void registerOptionalClinicalHistoryResources(Module module) EHRService.get().registerHistoryDataSource(new DefaultArrivalDataSource(module)); EHRService.get().registerHistoryDataSource(new DefaultAssignmentEndDataSource(module)); EHRService.get().registerHistoryDataSource(new DefaultBirthDataSource(module)); - EHRService.get().registerHistoryDataSource(new DefaultClinicalRemarksDataSource(module)); EHRService.get().registerHistoryDataSource(new DefaultDeathsDataSource(module)); EHRService.get().registerHistoryDataSource(new DefaultDepartureDataSource(module)); EHRService.get().registerHistoryDataSource(new DefaultDrugsDataSource(module)); @@ -456,7 +455,6 @@ public void registerOptionalClinicalHistoryResources(Module module) EHRService.get().registerLabworkType(new AntibioticSensitivityLabworkType(module)); EHRService.get().registerLabworkType(new ChemistryLabworkType(module)); EHRService.get().registerLabworkType(new HematologyLabworkType(module)); - EHRService.get().registerLabworkType(new iStatLabworkType(module)); EHRService.get().registerLabworkType(new MicrobiologyLabworkType(module)); EHRService.get().registerLabworkType(new MiscTestsLabworkType(module)); EHRService.get().registerLabworkType(new ParasitologyLabworkType(module)); @@ -680,6 +678,55 @@ public boolean hasPermission (String schemaName, String queryName, Container c, return EHRSecurityManager.get().testPermission(u, sr, perm, qcState); } + @Override + public void addIsActiveCol(AbstractTableInfo ti, boolean includeExpired, EndingOption... endOptions) + { + if (ti.getColumn("date") == null || ti.getColumn("enddate") == null) + { + return; + } + + String name = "isActive"; + if (ti.getColumn(name) == null) + { + SQLFragment sql = new SQLFragment("(CASE " + + // when the start is in the future, using whole-day increments, it is not active + " WHEN (CAST(" + ExprColumn.STR_TABLE_ALIAS + ".date as DATE) > {fn curdate()}) THEN " + ti.getSqlDialect().getBooleanFALSE() + + // when enddate is null, it is active + " WHEN (" + ExprColumn.STR_TABLE_ALIAS + ".enddate IS NULL) THEN " + ti.getSqlDialect().getBooleanTRUE()); + for (EHRService.EndingOption endOption : endOptions) + { + sql.append(endOption.getSql()); + } + sql.append( + " WHEN (CAST(" + ExprColumn.STR_TABLE_ALIAS + ".enddate AS DATE) > {fn curdate()}) THEN " + ti.getSqlDialect().getBooleanTRUE() + + " ELSE " + ti.getSqlDialect().getBooleanFALSE() + + " END)"); + + ExprColumn col = new ExprColumn(ti, name, sql, JdbcType.BOOLEAN, ti.getColumn("date"), ti.getColumn("enddate")); + col.setLabel("Is Active?"); + ti.addColumn(col); + } + + if (includeExpired) + { + String expired = "isExpired"; + if (ti.getColumn(expired) == null) + { + SQLFragment sql = new SQLFragment("(CASE " + + // any record with a null or future enddate (considering time) is active + " WHEN (" + ExprColumn.STR_TABLE_ALIAS + ".enddate IS NULL) THEN " + ti.getSqlDialect().getBooleanFALSE() + + " WHEN (" + ExprColumn.STR_TABLE_ALIAS + ".enddate < {fn now()}) THEN " + ti.getSqlDialect().getBooleanTRUE() + + " ELSE " + ti.getSqlDialect().getBooleanFALSE() + + " END)"); + + ExprColumn col = new ExprColumn(ti, expired, sql, JdbcType.BOOLEAN, ti.getColumn("enddate")); + col.setLabel("Is Expired?"); + ti.addColumn(col); + } + } + } + @Override public void customizeDateColumn(AbstractTableInfo ti, String colName) { diff --git a/ehr/src/org/labkey/ehr/history/ClinicalHistoryManager.java b/ehr/src/org/labkey/ehr/history/ClinicalHistoryManager.java index 13c79e1e6..7125beb0b 100644 --- a/ehr/src/org/labkey/ehr/history/ClinicalHistoryManager.java +++ b/ehr/src/org/labkey/ehr/history/ClinicalHistoryManager.java @@ -22,6 +22,7 @@ import org.labkey.api.security.User; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashSet; @@ -38,11 +39,13 @@ public class ClinicalHistoryManager { private static final ClinicalHistoryManager _instance = new ClinicalHistoryManager(); - private static final Logger _log = Logger.getLogger(ClinicalHistoryManager.class); - private final List _dataSources = new ArrayList<>(); + private List _dataSources = new ArrayList<>(); + private Logger _log = Logger.getLogger(ClinicalHistoryManager.class); - private ClinicalHistoryManager(){} + private ClinicalHistoryManager() + { + } public static ClinicalHistoryManager get() { @@ -72,7 +75,7 @@ public List getHistory(Container c, User u, String subjectId, Date m public Set getTypes(Container c, User u) { - Set types = new HashSet(); + Set types = new HashSet<>(); for (HistoryDataSource ds : getDataSources(c, u)) { @@ -100,7 +103,14 @@ public List getHistory(Container c, User u, String subjectId, String public void sortRowsByDate(List rows) { - rows.sort(Comparator.comparing(HistoryRow::getSortDateString, Comparator.reverseOrder())); + Collections.sort(rows, new Comparator() + { + @Override + public int compare(HistoryRow o1, HistoryRow o2) + { + return (-1 * (o1.getSortDateString().compareTo(o2.getSortDateString()))); + } + }); } protected List getDataSources(Container c, User u) diff --git a/ehr/src/org/labkey/ehr/history/DefaultLabworkDataSource.java b/ehr/src/org/labkey/ehr/history/DefaultLabworkDataSource.java index 2eb50cf81..bf19f1201 100644 --- a/ehr/src/org/labkey/ehr/history/DefaultLabworkDataSource.java +++ b/ehr/src/org/labkey/ehr/history/DefaultLabworkDataSource.java @@ -63,14 +63,15 @@ protected String getHtml(Container c, Results rs, boolean redacted) throws SQLEx { StringBuilder sb = new StringBuilder(); - if (!redacted) + if (!redacted && LabworkManager.get().showPerformedBy(c, rs.hasColumn(FieldKey.fromString("type")) ? rs.getString("type") : null)) + { sb.append(safeAppend(rs, "Performed By", "performedby")); + //Modified 10-13-2017 Blasa + sb.append(safeAppend(rs, "Testing Performed by", "createdby/DisplayName")); + } - //sb.append(safeAppend(rs, "Type", "type")); sb.append(safeAppend(rs, "Service/Panel", "servicerequested")); - //Modified 9-9-2015 Blasa - sb.append(safeAppend(rs, "Testing Performed by", "chargetype")); sb.append(safeAppend(rs, "Sample Type", "sampletype")); @@ -109,9 +110,8 @@ protected String getHtml(Container c, Results rs, boolean redacted) throws SQLEx @Override protected Set getColumnNames() { - //return PageFlowUtil.set("Id", "date", "enddate", "objectid", "type", "performedby", "sampletype", "tissue/meaning", "tissue", "collectionmethod", "method", "servicerequested", "remark"); - //Modified 9-9-2015 Added chargetype - return PageFlowUtil.set("Id", "date", "enddate", "objectid", "type", "performedby", "sampletype", "tissue/meaning", "tissue", "collectionmethod", "method", "servicerequested", "chargetype","remark"); + //Modified: 5-17-2017 R.Blasa + return PageFlowUtil.set("Id", "date", "enddate", "objectid", "type", "performedby", "sampletype", "tissue/meaning", "tissue", "collectionmethod", "method", "servicerequested", "createdby/DisplayName","remark"); } @Override diff --git a/ehr/src/org/labkey/ehr/history/LabworkManager.java b/ehr/src/org/labkey/ehr/history/LabworkManager.java index 1669c2f93..d87648306 100644 --- a/ehr/src/org/labkey/ehr/history/LabworkManager.java +++ b/ehr/src/org/labkey/ehr/history/LabworkManager.java @@ -15,6 +15,7 @@ */ package org.labkey.ehr.history; +import org.jetbrains.annotations.Nullable; import org.labkey.api.data.Container; import org.labkey.api.ehr.history.LabworkType; import org.labkey.api.security.User; @@ -110,4 +111,16 @@ private void merge(Map> map, Map> newM map.put(runId, existing); } } + + public boolean showPerformedBy(Container c, @Nullable String type) + { + for (LabworkType labworkType : _types) + { + if (labworkType.isEnabled(c) && labworkType.getName().equalsIgnoreCase(type)) + { + return labworkType.showPerformedBy(); + } + } + return true; + } } diff --git a/ehr/src/org/labkey/ehr/security/EHRProtocolManagementRole.java b/ehr/src/org/labkey/ehr/security/EHRProtocolManagementRole.java index e38cdf1f1..a87469312 100644 --- a/ehr/src/org/labkey/ehr/security/EHRProtocolManagementRole.java +++ b/ehr/src/org/labkey/ehr/security/EHRProtocolManagementRole.java @@ -27,6 +27,7 @@ * User: bimber * Date: 1/17/13 * Time: 7:42 PM +* 3/31/2017 jonesga removed ProjectEDit Permissions /// approved by j Eckels 3/30/2017 */ public class EHRProtocolManagementRole extends AbstractEHRRole { @@ -38,7 +39,7 @@ public EHRProtocolManagementRole() UpdatePermission.class, DeletePermission.class, EHRDataEntryPermission.class, - EHRProjectEditPermission.class, + EHRProtocolEditPermission.class ); } diff --git a/ehr/src/org/labkey/ehr/table/AbstractAgeDisplayColumn.java b/ehr/src/org/labkey/ehr/table/AbstractAgeDisplayColumn.java new file mode 100644 index 000000000..0df82846c --- /dev/null +++ b/ehr/src/org/labkey/ehr/table/AbstractAgeDisplayColumn.java @@ -0,0 +1,13 @@ +package org.labkey.ehr.table; + +import org.labkey.api.data.ColumnInfo; +import org.labkey.api.ehr.table.DurationColumn; + +public abstract class AbstractAgeDisplayColumn extends DurationColumn +{ + public AbstractAgeDisplayColumn(ColumnInfo col) + { + super(col, "birth", "lastDayAtCenter"); + setDropTime(true); + } +} diff --git a/ehr/src/org/labkey/ehr/table/AgeDisplayColumn.java b/ehr/src/org/labkey/ehr/table/AgeDisplayColumn.java index 7c6d965f4..8044b7846 100644 --- a/ehr/src/org/labkey/ehr/table/AgeDisplayColumn.java +++ b/ehr/src/org/labkey/ehr/table/AgeDisplayColumn.java @@ -16,8 +16,8 @@ package org.labkey.ehr.table; import org.apache.commons.lang3.time.DurationFormatUtils; +import org.jetbrains.annotations.NotNull; import org.labkey.api.data.ColumnInfo; -import org.labkey.api.ehr.table.DurationColumn; import java.util.Calendar; import java.util.Date; @@ -27,25 +27,16 @@ * Date: 10/23/13 * Time: 3:49 PM */ -public class AgeDisplayColumn extends DurationColumn +public class AgeDisplayColumn extends AbstractAgeDisplayColumn { public AgeDisplayColumn(ColumnInfo col) { - super(col, "birth", "lastDayAtCenter"); + super(col); } @Override - public String getFormattedDuration(Date startDate, Date endDate) + public String getFormattedDuration(@NotNull Calendar birthCal, @NotNull Calendar deathCal) { - if (startDate == null) - return null; - - Calendar birthCal = Calendar.getInstance(); - birthCal.setTime(startDate); - - Calendar deathCal = Calendar.getInstance(); - deathCal.setTime(endDate == null ? new Date() : endDate); - String yearMonthPartFromUtil; String yearDayPartFromUtil; try diff --git a/ehr/src/org/labkey/ehr/table/AgeMonthsDisplayColumn.java b/ehr/src/org/labkey/ehr/table/AgeMonthsDisplayColumn.java index f9e109124..a57b836f7 100644 --- a/ehr/src/org/labkey/ehr/table/AgeMonthsDisplayColumn.java +++ b/ehr/src/org/labkey/ehr/table/AgeMonthsDisplayColumn.java @@ -16,8 +16,8 @@ package org.labkey.ehr.table; import org.apache.commons.lang3.time.DurationFormatUtils; +import org.jetbrains.annotations.NotNull; import org.labkey.api.data.ColumnInfo; -import org.labkey.api.ehr.table.DurationColumn; import java.util.Calendar; import java.util.Date; @@ -27,29 +27,20 @@ * Date: 10/23/13 * Time: 3:49 PM */ -public class AgeMonthsDisplayColumn extends DurationColumn +public class AgeMonthsDisplayColumn extends AbstractAgeDisplayColumn { public AgeMonthsDisplayColumn(ColumnInfo col) { - super(col, "birth", "lastDayAtCenter"); + super(col); } @Override - protected String getFormattedDuration(Date startDate, Date endDate) + protected String getFormattedDuration(@NotNull Calendar startDate, @NotNull Calendar endDate) { - if (startDate == null) - return null; - - Calendar birthCal = Calendar.getInstance(); - birthCal.setTime(startDate); - - Calendar deathCal = Calendar.getInstance(); - deathCal.setTime(endDate == null ? new Date() : endDate); - String monthDayPartFromUtil; try { - monthDayPartFromUtil = DurationFormatUtils.formatPeriod(birthCal.getTimeInMillis(), deathCal.getTimeInMillis(), "M:d"); + monthDayPartFromUtil = DurationFormatUtils.formatPeriod(startDate.getTimeInMillis(), endDate.getTimeInMillis(), "M:d"); } catch (IllegalArgumentException iae) { diff --git a/ehr/src/org/labkey/ehr/table/AgeYearMonthsDisplayColumn.java b/ehr/src/org/labkey/ehr/table/AgeYearMonthsDisplayColumn.java index 058f7587b..ed2b2039c 100644 --- a/ehr/src/org/labkey/ehr/table/AgeYearMonthsDisplayColumn.java +++ b/ehr/src/org/labkey/ehr/table/AgeYearMonthsDisplayColumn.java @@ -16,31 +16,22 @@ package org.labkey.ehr.table; import org.apache.commons.lang3.time.DurationFormatUtils; +import org.jetbrains.annotations.NotNull; import org.labkey.api.data.ColumnInfo; -import org.labkey.api.ehr.table.DurationColumn; import java.util.Calendar; import java.util.Date; -public class AgeYearMonthsDisplayColumn extends DurationColumn +public class AgeYearMonthsDisplayColumn extends AbstractAgeDisplayColumn { public AgeYearMonthsDisplayColumn(ColumnInfo col) { - super(col, "birth", "lastDayAtCenter"); + super(col); } @Override - protected String getFormattedDuration(Date startDate, Date endDate) + protected String getFormattedDuration(@NotNull Calendar birthCal, @NotNull Calendar deathCal) { - if (startDate == null) - return null; - - Calendar birthCal = Calendar.getInstance(); - birthCal.setTime(startDate); - - Calendar deathCal = Calendar.getInstance(); - deathCal.setTime(endDate == null ? new Date() : endDate); - String yearMonthPartFromUtil; try { diff --git a/ehr/src/org/labkey/ehr/table/AgeYearsMonthsDaysDisplayColumn.java b/ehr/src/org/labkey/ehr/table/AgeYearsMonthsDaysDisplayColumn.java index 5e9184c17..69b630810 100644 --- a/ehr/src/org/labkey/ehr/table/AgeYearsMonthsDaysDisplayColumn.java +++ b/ehr/src/org/labkey/ehr/table/AgeYearsMonthsDaysDisplayColumn.java @@ -16,31 +16,22 @@ package org.labkey.ehr.table; import org.apache.commons.lang3.time.DurationFormatUtils; +import org.jetbrains.annotations.NotNull; import org.labkey.api.data.ColumnInfo; -import org.labkey.api.ehr.table.DurationColumn; import java.util.Calendar; import java.util.Date; -public class AgeYearsMonthsDaysDisplayColumn extends DurationColumn +public class AgeYearsMonthsDaysDisplayColumn extends AbstractAgeDisplayColumn { public AgeYearsMonthsDaysDisplayColumn(ColumnInfo col) { - super(col, "birth", "lastDayAtCenter"); + super(col); } @Override - protected String getFormattedDuration(Date startDate, Date endDate) + protected String getFormattedDuration(@NotNull Calendar birthCal, @NotNull Calendar deathCal) { - if (startDate == null) - return null; - - Calendar birthCal = Calendar.getInstance(); - birthCal.setTime(startDate); - - Calendar deathCal = Calendar.getInstance(); - deathCal.setTime(endDate == null ? new Date() : endDate); - String formattedAge; try { diff --git a/ehr/src/org/labkey/ehr/table/DefaultEHRCustomizer.java b/ehr/src/org/labkey/ehr/table/DefaultEHRCustomizer.java index 60f9927d1..268835004 100644 --- a/ehr/src/org/labkey/ehr/table/DefaultEHRCustomizer.java +++ b/ehr/src/org/labkey/ehr/table/DefaultEHRCustomizer.java @@ -41,6 +41,7 @@ import org.labkey.api.ehr.buttons.EHRShowEditUIButton; import org.labkey.api.ehr.security.EHRDataAdminPermission; import org.labkey.api.exp.api.StorageProvisioner; +import org.labkey.api.exp.property.Domain; import org.labkey.api.gwt.client.AuditBehaviorType; import org.labkey.api.gwt.client.FacetingBehaviorType; import org.labkey.api.ldk.LDKService; @@ -454,7 +455,7 @@ private void customizeDataset(DatasetTable ds) if (matches(ti, "study", "Treatment Orders")) { - addIsActiveColWithTime(ti); + addIsActiveCol(ti, true, EHRService.EndingOption.endingBeforeNow); } } else if (matches(ti, "study", "Clinical Encounters") || matches(ti, "study", "Encounters")) @@ -479,7 +480,7 @@ else if (matches(ti, "study", "pathologyDiagnoses") || matches(ti, "study", "Pat } else if (matches(ti, "study", "housing")) { - addIsActiveColWithTime(ti); + addIsActiveCol(ti, true, EHRService.EndingOption.endingBeforeNow); } else if (matches(ti, "study", "blood") || matches(ti, "study", "Blood Draws")) { @@ -503,16 +504,20 @@ else if (matches(ti, "study", "problem") || matches(ti, "study", "problem list") } else if (matches(ti, "study", "flags") || matches(ti, "study", "Animal Record Flags")) { - addIsActiveCol(ti, false); + addIsActiveCol(ti, false, EHRService.EndingOption.activeAfterMidnightTonight); } else if (matches(ti, "study", "diet")) { addIsActiveCol(ti); } - else if (matches(ti, "study", "parentage")) + else if (matches(ti, "study", "geneticAncestry")) { addIsActiveCol(ti, false); } + else if (matches(ti, "study", "parentage")) + { + addIsActiveCol(ti, false, EHRService.EndingOption.activeAfterMidnightTonight); + } else if (matches(ti, "study", "demographics")) { customizeDemographics(ti); @@ -531,41 +536,13 @@ else if (matches(ti, "study", "arrival")) private void addIsActiveCol(AbstractTableInfo ti) { - addIsActiveCol(ti, true); + addIsActiveCol(ti, false, EHRService.EndingOption.activeAfterMidnightTonight, EHRService.EndingOption.allowSameDay); } - private void addIsActiveCol(AbstractTableInfo ti, boolean allowSameDay) - { - addIsActiveCol(ti, allowSameDay, false); - } - private void addIsActiveCol(AbstractTableInfo ti, boolean allowSameDay, boolean allowDateOfDeath) + private void addIsActiveCol(AbstractTableInfo ti, boolean includeExpired, EHRService.EndingOption... endOptions) { - if (ti.getColumn("date") == null || ti.getColumn("enddate") == null) - { - return; - } - - String name = "isActive"; - if (ti.getColumn(name, false) == null) - { - SQLFragment sql = new SQLFragment("(CASE " + - // when the start is in the future, using whole-day increments, it is not active - " WHEN (CAST(" + ExprColumn.STR_TABLE_ALIAS + ".date as DATE) > {fn curdate()}) THEN " + ti.getSqlDialect().getBooleanFALSE() + - // when enddate is null, it is active - " WHEN (" + ExprColumn.STR_TABLE_ALIAS + ".enddate IS NULL) THEN " + ti.getSqlDialect().getBooleanTRUE() + - // if allowSameDay=true, then consider records that start/stop on today's date to be active - (allowSameDay ? " WHEN (" + ExprColumn.STR_TABLE_ALIAS + ".enddate IS NOT NULL AND CAST(" + ExprColumn.STR_TABLE_ALIAS + ".enddate AS DATE) = {fn curdate()} AND CAST(" + ExprColumn.STR_TABLE_ALIAS + ".date as DATE) = {fn curdate()}) THEN " + ti.getSqlDialect().getBooleanTRUE() : "") + - // if enddate is in the future (whole-day increments), then it is active - " WHEN (CAST(" + ExprColumn.STR_TABLE_ALIAS + ".enddate AS DATE) > {fn curdate()}) THEN " + ti.getSqlDialect().getBooleanTRUE() + - //(allowDateOfDeath ? " WHEN " + ExprColumn.STR_TABLE_ALIAS : "") + - " ELSE " + ti.getSqlDialect().getBooleanFALSE() + - " END)"); - - ExprColumn col = new ExprColumn(ti, name, sql, JdbcType.BOOLEAN, ti.getColumn("date"), ti.getColumn("enddate")); - col.setLabel("Is Active?"); - ti.addColumn(col); - } + EHRService.get().addIsActiveCol(ti, includeExpired, endOptions); } //note: intended specially for treatment orders, but also used for housing. note slightly unusual behavior around start date @@ -1300,7 +1277,7 @@ private void customizeDrugsUnified(AbstractTableInfo ti) { doSharedCustomization(ti); addUnitColumns(ti); - addIsActiveColWithTime(ti); + addIsActiveCol(ti, true, EHRService.EndingOption.endingBeforeNow); } private void customizeTasks(AbstractTableInfo ti) @@ -1779,6 +1756,7 @@ public TableInfo getLookupTableInfo() " ROUND(CONVERT(age_in_months(d.birth, CAST(c." + dateColName + " as DATE)), DOUBLE) / 12, 1)\n" + "END AS float) as AgeAtTime,\n" + "\n" + + "CAST(\n" + "CASE\n" + "WHEN d.birth is null or c." + dateColName + " is null\n" + @@ -1799,6 +1777,18 @@ public TableInfo getLookupTableInfo() " floor(age(d.birth, CAST(c." + dateColName + " as DATE)))\n" + "END AS float) as AgeAtTimeYearsRounded,\n" + "\n" + + //Added 'Age at time Days' by kollil on 02/15/2019 + "CAST(\n" + + "CASE\n" + + "WHEN d.birth is null or c." + dateColName + " is null\n" + + " THEN null\n" + + "WHEN (d.lastDayAtCenter IS NOT NULL AND d.lastDayAtCenter < c." + dateColName + ") THEN\n" + + " CONVERT(TIMESTAMPDIFF('SQL_TSI_DAY',d.birth, d.lastDayAtCenter), INTEGER)\n" + + "ELSE\n" + + " CONVERT(TIMESTAMPDIFF('SQL_TSI_DAY',d.birth, CAST(c." + dateColName + " AS DATE)), INTEGER)\n" + + "END AS float) as AgeAtTimeDays,\n" + + "\n" + + // "CAST(\n" + "CASE\n" + "WHEN d.birth is null or c." + dateColName + " is null\n" + diff --git a/ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java b/ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java index e36404d2d..35bf8d485 100644 --- a/ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java +++ b/ehr/src/org/labkey/ehr/utils/TriggerScriptHelper.java @@ -367,8 +367,21 @@ public String validateAssignment(String id, Integer projectId, Date date) if (protocol == null) return "This project is not associated with a valid protocol"; - ProjectValidator validator = EHRService.get().getProjectValidator(); - return validator != null ? validator.validateAssignment(id, projectId, date, _user, getContainer(), protocol) : null; + TableInfo ti = getTableInfo("study", "Assignment"); + SimpleFilter filter = new SimpleFilter(FieldKey.fromString("Id"), id); + + filter.addCondition(FieldKey.fromString("date"), date, CompareType.DATE_LTE); + filter.addClause(new SimpleFilter.OrClause(new CompareType.EqualsCompareClause(FieldKey.fromString("project"), CompareType.EQUAL, projectId), new CompareType.CompareClause(FieldKey.fromString("project/protocol"), CompareType.EQUAL, protocol))); + filter.addClause(new SimpleFilter.OrClause(CompareType.DATE_GTE.createFilterClause(FieldKey.fromString("enddate"), date), new CompareType.CompareClause(FieldKey.fromString("enddate"), CompareType.ISBLANK, null))); + filter.addCondition(FieldKey.fromString("qcstate/publicdata"), true, CompareType.EQUAL); + + TableSelector ts = new TableSelector(ti, PageFlowUtil.set("project"), filter, null); + if (!ts.exists()) + { + return "Not assigned to the protocol on this date"; + } + + return null; } public String getAccountForProject(int projectId) @@ -1576,14 +1589,40 @@ public void updateStatusField(List ids, Map> liveBirt // NOTE: this behavior around live births is an imperfect way to mesh WNPRC/ONPRC rules. ONPRC records records in the birth table, // including dead infants. all records in the WNPRC table are of live births. checking for the column 'birth_condition' column is a crude proxy for this TableInfo birthTable = getTableInfo("study", "birth"); + TableInfo arrivalTable = getTableInfo("study", "Arrival"); //note: allow draft records to count SimpleFilter deadBirthFilter = new SimpleFilter(FieldKey.fromString("birth_condition/alive"), false); deadBirthFilter.addCondition(FieldKey.fromString("birth_condition"), null, CompareType.NONBLANK); - Date lastDeadBirth = birthTable.getColumnNameSet().contains("birth_condition") ? findMostRecentDate(id, getMostRecentDate(id, birthTable, deadBirthFilter), null) : null; - Date lastLiveBirth = findMostRecentDate(id, getMostRecentDate(id, birthTable, (birthTable.getColumnNameSet().contains("birth_condition") ? new SimpleFilter(FieldKey.fromString("birth_condition/alive"), false, CompareType.NEQ_OR_NULL) : null)), liveBirths); + boolean hasBirthConditionCol = birthTable.getColumnNameSet().contains("birth_condition"); + boolean hasArrivalAcquiTypeCol = arrivalTable.getColumnNameSet().contains("acquisitionType"); + Date lastDeadBirth = hasBirthConditionCol ? findMostRecentDate(id, getMostRecentDate(id, birthTable, deadBirthFilter), null) : null; + Date lastLiveBirth = findMostRecentDate(id, getMostRecentDate(id, birthTable, (hasBirthConditionCol ? new SimpleFilter(FieldKey.fromString("birth_condition/alive"), false, CompareType.NEQ_OR_NULL) : null)), liveBirths); - String status = null; - if (lastDeath != null || lastDeadBirth != null) + String birthCondition = null; + String acquitype = null; + if (hasBirthConditionCol) + { + TableSelector ts = new TableSelector(birthTable, Collections.singleton("birth_condition"), new SimpleFilter(FieldKey.fromParts("Id"), id), null); + birthCondition = ts.getObject(String.class); + } + if (hasArrivalAcquiTypeCol) + { + FieldKey acquisitionFieldKey = FieldKey.fromParts("acquisitionType", "value"); + Map columns = QueryService.get().getColumns(arrivalTable, Collections.singleton(acquisitionFieldKey)); + ColumnInfo acquisitionColumn = columns.get(acquisitionFieldKey); + TableSelector ts = new TableSelector(arrivalTable, Collections.singleton(acquisitionColumn), new SimpleFilter(FieldKey.fromParts("Id"), id), null); + acquitype = ts.getObject(String.class); + } + String status; + if ("Fetus - Prenatal".equalsIgnoreCase(birthCondition) ) + { + status = "Fetus"; + } + else if ("Pending Arrival".equalsIgnoreCase(acquitype)) + { + status = "Pending"; + } + else if (lastDeath != null || lastDeadBirth != null) { status = "Dead"; } diff --git a/ehr/test/src/org/labkey/test/tests/ehr/AbstractEHRTest.java b/ehr/test/src/org/labkey/test/tests/ehr/AbstractEHRTest.java index bac68b0af..606531c24 100644 --- a/ehr/test/src/org/labkey/test/tests/ehr/AbstractEHRTest.java +++ b/ehr/test/src/org/labkey/test/tests/ehr/AbstractEHRTest.java @@ -36,10 +36,12 @@ import org.labkey.test.pages.ehr.AnimalHistoryPage; import org.labkey.test.util.AdvancedSqlTest; import org.labkey.test.util.ApiPermissionsHelper; +import org.labkey.test.util.ListHelper; import org.labkey.test.util.LogMethod; import org.labkey.test.util.LoggedParam; import org.labkey.test.util.PasswordUtil; import org.labkey.test.util.PermissionsHelper; +import org.labkey.test.util.SchemaHelper; import org.labkey.test.util.ehr.EHRClientAPIHelper; import org.labkey.test.util.ehr.EHRTestHelper; import org.labkey.test.util.ext4cmp.Ext4CmpRef; @@ -363,6 +365,9 @@ protected void initProject(String type) throws Exception createUsersandPermissions();//note: we create the users prior to study import, b/c that user is used by TableCustomizers if(type.equals("CNPRC EHR") || type.equals("TNPRC EHR")) _setupHelper.loadEHRTableDefinitions(); + if(type.equals("ONPRC EHR")) + onprcSetupBeforeStudyUpload(); //this needs to happen before import study() below so that 'Validation Queries' step doesn't fail since the queries depend on setup in this method. + populateInitialData(); importStudy(); disableMiniProfiler(); @@ -373,6 +378,67 @@ protected void initProject(String type) throws Exception primeCaches(); } + private void onprcSetupBeforeStudyUpload() + { + //create onprc_billing_public linked schema + beginAt(getProjectName()); + SchemaHelper schemaHelper = new SchemaHelper(this); + schemaHelper.createLinkedSchema(this.getProjectName(), null, "onprc_billing_public", "/" + this.getContainerPath(), "onprc_billing_public", null, null, null); + + //create Labfee_NoChargeProjects + beginAt(getProjectName()); + + ListHelper.ListColumn projectCol= new ListHelper.ListColumn("project", ListHelper.ListColumnType.Integer); + ListHelper.ListColumn startDateCol= new ListHelper.ListColumn("startDate", ListHelper.ListColumnType.DateAndTime); + ListHelper.ListColumn dateDisabledCol= new ListHelper.ListColumn("dateDisabled", ListHelper.ListColumnType.DateAndTime); + ListHelper.ListColumn createdDbCol= new ListHelper.ListColumn("Createdb", ListHelper.ListColumnType.Integer); + ListHelper.ListColumn notesCol= new ListHelper.ListColumn("Notes", ListHelper.ListColumnType.String); + _listHelper.createList(getProjectName(), "Labfee_NoChargeProjects", ListHelper.ListColumnType.Integer, "key", projectCol, startDateCol, dateDisabledCol, createdDbCol, notesCol); + + _listHelper.createList(getProjectName(), "GeneticValue", ListHelper.ListColumnType.String, "Id", + new ListHelper.ListColumn("meanKinship", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("zscore", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("genomeUniqueness", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("totalOffspring", ListHelper.ListColumnType.Integer), + new ListHelper.ListColumn("livingOffspring", ListHelper.ListColumnType.Integer), + new ListHelper.ListColumn("assignments", ListHelper.ListColumnType.Integer), + new ListHelper.ListColumn("condition", ListHelper.ListColumnType.String), + new ListHelper.ListColumn("import", ListHelper.ListColumnType.String), + new ListHelper.ListColumn("value", ListHelper.ListColumnType.String), + new ListHelper.ListColumn("rank", ListHelper.ListColumnType.Integer) + ); + + _listHelper.createList(getProjectName(), "Special_Aliases", ListHelper.ListColumnType.AutoInteger, "Key", + new ListHelper.ListColumn("Category", ListHelper.ListColumnType.String), + new ListHelper.ListColumn("Alias", ListHelper.ListColumnType.String)); + + // Fake up an external schema connection for "dbo" via a list and a linked schema + _listHelper.createList(getProjectName(), "Rpt_ChargesProjection", ListHelper.ListColumnType.AutoInteger, "RowId", + new ListHelper.ListColumn("ChargeId", ListHelper.ListColumnType.Integer), + new ListHelper.ListColumn("UnitCost", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("year1", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("year2", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("year3", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("year4", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("year5", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("year6", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("year7", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("year8", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate1", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate2", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate3", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate4", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate5", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate6", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate7", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate8", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("Aprate9", ListHelper.ListColumnType.Decimal), + new ListHelper.ListColumn("PostedDate", ListHelper.ListColumnType.DateAndTime) + ); + schemaHelper.createLinkedSchema(this.getProjectName(), null, "dbo", "/" + this.getContainerPath(), null, "lists", null, null); + + } + @LogMethod(quiet = true) protected void populate(@LoggedParam String tableLabel) { diff --git a/ehr/test/src/org/labkey/test/tests/external/onprc/ONPRC_BillingTest.java b/ehr/test/src/org/labkey/test/tests/external/onprc/ONPRC_BillingTest.java index 315a79a04..ad4b4e7b8 100644 --- a/ehr/test/src/org/labkey/test/tests/external/onprc/ONPRC_BillingTest.java +++ b/ehr/test/src/org/labkey/test/tests/external/onprc/ONPRC_BillingTest.java @@ -156,19 +156,6 @@ protected boolean skipStudyImportQueryValidation() return true; } - @Override - protected void setEHRModuleProperties(ModulePropertyValue... extraProps) - { - clickProject(PROJECT_NAME); - super._containerHelper.enableModule("ONPRC_Billing"); - super._containerHelper.enableModule("ONPRC_BillingPublic"); - super._containerHelper.enableModule("SLA"); - super.setEHRModuleProperties( - new ModulePropertyValue("ONPRC_Billing", "/" + getProjectName(), "BillingContainer", "/" + getContainerPath()), - new ModulePropertyValue("SLA", "/" + getProjectName(), "SLAContainer", "/" + getContainerPath()) - ); - } - @Override protected void populateInitialData() { diff --git a/ehr/test/src/org/labkey/test/tests/onprc_ehr/AbstractGenericONPRC_EHRTest.java b/ehr/test/src/org/labkey/test/tests/onprc_ehr/AbstractGenericONPRC_EHRTest.java index 35cfea104..2d9f6430f 100644 --- a/ehr/test/src/org/labkey/test/tests/onprc_ehr/AbstractGenericONPRC_EHRTest.java +++ b/ehr/test/src/org/labkey/test/tests/onprc_ehr/AbstractGenericONPRC_EHRTest.java @@ -26,6 +26,7 @@ import org.labkey.remoteapi.query.SelectRowsCommand; import org.labkey.remoteapi.query.SelectRowsResponse; import org.labkey.test.Locator; +import org.labkey.test.ModulePropertyValue; import org.labkey.test.TestFileUtils; import org.labkey.test.WebTestHelper; import org.labkey.test.tests.ehr.AbstractGenericEHRTest; @@ -91,6 +92,22 @@ protected EHRClientAPIHelper getApiHelper() return new EHRClientAPIHelper(this, getContainerPath()); } + @Override + protected void setEHRModuleProperties(ModulePropertyValue... extraProps) + { + log("Setting EHR Module Properties"); + clickProject(getProjectName()); + super._containerHelper.enableModule("ONPRC_Billing"); + super._containerHelper.enableModule("ONPRC_BillingPublic"); + super._containerHelper.enableModule("SLA"); + super.setEHRModuleProperties( + new ModulePropertyValue("ONPRC_Billing", "/" + getProjectName(), "BillingContainer", "/" + getContainerPath()), + new ModulePropertyValue("ONPRC_Billing", "/" + getProjectName(), "BillingContainer_Public", "/" + getContainerPath()), + new ModulePropertyValue("SLA", "/" + getProjectName(), "SLAContainer", "/" + getContainerPath()), + new ModulePropertyValue("ONPRC_EHR", "/" + getProjectName(), "DCM_NHP_Resources_Container", "/" + getContainerPath()) + ); + } + @Override protected void importStudy() { diff --git a/ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java b/ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java index 417674bf7..58c513905 100644 --- a/ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java +++ b/ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java @@ -19,15 +19,13 @@ import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.tuple.Pair; import org.json.simple.JSONArray; -import org.json.simple.JSONObject; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; -import org.labkey.remoteapi.PostCommand; +import org.labkey.remoteapi.CommandException; import org.labkey.remoteapi.query.Filter; import org.labkey.remoteapi.query.InsertRowsCommand; -import org.labkey.remoteapi.query.SaveRowsResponse; import org.labkey.remoteapi.query.SelectRowsCommand; import org.labkey.remoteapi.query.SelectRowsResponse; import org.labkey.remoteapi.query.Sort; @@ -46,10 +44,10 @@ import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.Ext4Helper; import org.labkey.test.util.LogMethod; -import org.labkey.test.util.LoggedParam; import org.labkey.test.util.Maps; import org.labkey.test.util.PasswordUtil; import org.labkey.test.util.RReportHelper; +import org.labkey.test.util.SchemaHelper; import org.labkey.test.util.ehr.EHRClientAPIHelper; import org.labkey.test.util.ext4cmp.Ext4CmpRef; import org.labkey.test.util.ext4cmp.Ext4ComboRef; @@ -60,10 +58,10 @@ import org.openqa.selenium.WebElement; import java.io.File; +import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; -import java.time.temporal.TemporalUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -74,7 +72,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.TreeMap; import static org.junit.Assert.assertEquals; @@ -86,7 +83,6 @@ public class ONPRC_EHRTest extends AbstractGenericONPRC_EHRTest private boolean _hasCreatedBirthRecords = false; private String ANIMAL_HISTORY_URL = "/ehr/" + getProjectName() + "/animalHistory.view?"; - @Override protected String getProjectName() { @@ -108,6 +104,7 @@ public static void doSetup() throws Exception initTest.initProject(); initTest.createTestSubjects(); new RReportHelper(initTest).ensureRConfig(); + } @Override @@ -116,25 +113,6 @@ protected boolean doSetUserPasswords() return true; } - @Test - public void testBloodVolumeApi() throws Exception - { - UpdateRowsCommand updateRowsCommand = new UpdateRowsCommand("ehr_lookups", "species"); - updateRowsCommand.addRow(Maps.of("common", "Rhesus", "blood_draw_interval", 21)); - updateRowsCommand.addRow(Maps.of("common", "Cynomolgus", "blood_draw_interval", 21)); - updateRowsCommand.addRow(Maps.of("common", "Marmoset", "blood_draw_interval", 21)); - SaveRowsResponse saveResponse = updateRowsCommand.execute(getApiHelper().getConnection(), getContainerPath()); - assertEquals(3, saveResponse.getRowsAffected().intValue()); - - //refresh caches to match new blood volumes. this really should be automatic on the server - beginAt(WebTestHelper.buildURL("ehr", getContainerPath(), "primeDataEntryCache")); - waitAndClickAndWait(Locator.lkButton("OK")); - - testBloodDrawForAnimal(SUBJECTS[0]); - testBloodDrawForAnimal(SUBJECTS[1]); - testBloodDrawForAnimal(SUBJECTS[2]); - } - @Test public void testOverriddenActions() throws Exception { @@ -152,387 +130,10 @@ public void testOverriddenActions() throws Exception waitForElement(Locator.tagContainingText("a", "View Active Animal Assignments")); } - - private void testBloodDrawForAnimal(@LoggedParam String animalId) throws Exception - { - log("processing blood draws for: " + animalId); - - SelectRowsCommand select = new SelectRowsCommand("study", "demographics"); - select.addFilter(new Filter("Id", animalId, Filter.Operator.EQUAL)); - SelectRowsResponse resp = select.execute(getApiHelper().getConnection(), getContainerPath()); - Assert.assertEquals(1, resp.getRows().size()); - - Map demographicsRow = resp.getRows().get(0); - String species = (String) demographicsRow.get("species"); - - //find allowable volume - SelectRowsCommand select2 = new SelectRowsCommand("ehr_lookups", "species"); - select2.addFilter(new Filter("common", species, Filter.Operator.EQUAL)); - SelectRowsResponse resp2 = select2.execute(getApiHelper().getConnection(), getContainerPath()); - Assert.assertEquals(1, resp2.getRows().size()); - - Double bloodPerKg = (Double) resp2.getRows().get(0).get("blood_per_kg"); - Assert.assertTrue("Bad 'blood_per_kg': " + bloodPerKg, bloodPerKg > 0); - Double maxDrawPct = (Double) resp2.getRows().get(0).get("max_draw_pct"); - Assert.assertTrue("Bad 'max_draw_pct': " + maxDrawPct, maxDrawPct > 0); - Integer bloodDrawInterval = ((Double) resp2.getRows().get(0).get("blood_draw_interval")).intValue(); - Assert.assertEquals("Bad 'blood_draw_interval': " + bloodDrawInterval, 21, bloodDrawInterval.intValue()); - - log("Creating blood draws"); - Calendar startCal = Calendar.getInstance(); - startCal.setTime(DateUtils.truncate(new Date(), Calendar.DATE)); - startCal.add(Calendar.DATE, -15); - startCal.add(Calendar.HOUR, 12); - Object[][] bloodData = new Object[][]{ - {animalId, prepareDate(startCal.getTime(), -1, 0), 1.0, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 0, 0), 1.5, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 1, -4), 2.0, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 1, 0), 2.0, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 1, 4), 2.0, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 2, 0), 1.0, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 3, 1), 1.5, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 4, 0), 2.0, EHRQCState.REVIEW_REQUIRED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 5, 4), 1.0, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 4, -2), 2.0, EHRQCState.COMPLETED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 5, 0), 1.0, EHRQCState.REVIEW_REQUIRED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 5, 2), 1.0, EHRQCState.IN_PROGRESS.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), 5, 0), 1.0, EHRQCState.IN_PROGRESS.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval - 1, 0), 1.5, EHRQCState.REQUEST_PENDING.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval, 0), 2.0, EHRQCState.REQUEST_APPROVED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval + 1, 0), 2.0, EHRQCState.REQUEST_PENDING.label, generateGUID()}, - //add draw far in future - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval + bloodDrawInterval - 1, 0), 2.0, EHRQCState.REQUEST_APPROVED.label, generateGUID()}, - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval + bloodDrawInterval + 1, 0), 2.0, EHRQCState.REQUEST_APPROVED.label, generateGUID()} - }; - - PostCommand insertCommand = getApiHelper().prepareInsertCommand("study", "blood", "lsid", new String[]{"Id", "date", "quantity", "QCStateLabel", "objectid"}, bloodData); - getApiHelper().deleteAllRecords("study", "blood", new Filter("Id", animalId, Filter.Operator.EQUAL)); - getApiHelper().doSaveRows(DATA_ADMIN.getEmail(), insertCommand, getExtraContext()); - - log("Creating weight records"); - Object[][] weightData = new Object[][]{ - {animalId, prepareDate(startCal.getTime(), -1, 0), 5.0, EHRQCState.COMPLETED.label}, - {animalId, prepareDate(startCal.getTime(), 5, 0), 4.0, EHRQCState.COMPLETED.label}, - {animalId, prepareDate(startCal.getTime(), 5, 1), 2.0, EHRQCState.COMPLETED.label}, - {animalId, prepareDate(startCal.getTime(), 10, 1), 6.0, EHRQCState.COMPLETED.label} - }; - Map weightByDay = new TreeMap<>(); - weightByDay.put(prepareDate(startCal.getTime(), -1, 0), 5.0); - weightByDay.put(prepareDate(startCal.getTime(), 5, 0), 3.0); - weightByDay.put(prepareDate(startCal.getTime(), 5, 1), 3.0); - weightByDay.put(prepareDate(startCal.getTime(), 10, 1), 6.0); - - PostCommand insertCommand2 = getApiHelper().prepareInsertCommand("study", "weight", "lsid", new String[]{"Id", "date", "weight", "QCStateLabel"}, weightData); - getApiHelper().deleteAllRecords("study", "weight", new Filter("Id", animalId, Filter.Operator.EQUAL)); - getApiHelper().doSaveRows(DATA_ADMIN.getEmail(), insertCommand2, getExtraContext()); - - //validate results - //build map of daws by day: - Map bloodByDay = new TreeMap<>(); - for (Object[] row : bloodData) - { - Date d = DateUtils.truncate(row[1], Calendar.DATE); - String qcLabel = (String) row[3]; - Double vol = bloodByDay.containsKey(d) ? bloodByDay.get(d) : 0.0; - - //NOTE: we are including all QCStates - vol += (Double) row[2]; - - bloodByDay.put(d, vol); - } - - SelectRowsCommand select1 = new SelectRowsCommand("study", "blood"); - select1.setColumns(Arrays.asList("Id", "date", "quantity", "BloodRemaining/lastWeight", "BloodRemaining/allowableBlood", "BloodRemaining/previousBlood", "BloodRemaining/availableBlood", "BloodRemaining/minDate")); - Sort sort = new Sort("date"); - sort.setDirection(Sort.Direction.DESCENDING); - select1.setSorts(Arrays.asList(sort)); - select1.addFilter(new Filter("Id", animalId, Filter.Operator.EQUAL)); - SelectRowsResponse resp1 = select1.execute(getApiHelper().getConnection(), getContainerPath()); - - /*TODO: bloodSummary.sql and demographicsBloodSummary.sql seem to have changed functionality to only show the - current blood availability instead of historical and scheduled blood data as well. Removed parts of test - associated with these queries until we know if this is a desired change. - */ - - //validate blood draws, which really hits bloodSummary.sql -// for (Map row : resp1.getRows()) -// { -// Date rowDate = (Date) row.get("date"); -// -// Calendar minDate = Calendar.getInstance(); -// minDate.setTime(DateUtils.truncate(rowDate, Calendar.DATE)); -// minDate.add(Calendar.DATE, (-1 * bloodDrawInterval) + 1); -// -// Date rowMinDate = row.get("BloodRemaining/minDate") instanceof Date ? (Date) row.get("BloodRemaining/minDate") : _df.parse(row.get("BloodRemaining/minDate").toString()); -// Assert.assertEquals(minDate.getTime(), rowMinDate); -// -// Double lastWeight = null; -// for (Date weightDate : weightByDay.keySet()) -// { -// if (rowDate.getTime() >= DateUtils.truncate(weightDate, Calendar.DATE).getTime()) -// { -// lastWeight = weightByDay.get(weightDate); -// } -// } -// -// Assert.assertEquals(lastWeight, row.get("BloodRemaining/lastWeight")); -// Double previousBlood = 0.0; -// for (Date bloodDate : bloodByDay.keySet()) -// { -// //we want any draws GTE the min date considered and LTE the row's date -// if (bloodDate.getTime() >= minDate.getTime().getTime() && bloodDate.getTime() <= DateUtils.truncate(rowDate, Calendar.DATE).getTime()) -// { -// previousBlood += bloodByDay.get(bloodDate); -// } -// } -// Assert.assertEquals(previousBlood, row.get("BloodRemaining/previousBlood")); -// -// Double allowableBlood = lastWeight * bloodPerKg * maxDrawPct; -// Assert.assertEquals(allowableBlood, row.get("BloodRemaining/allowableBlood")); -// -// Double availableBlood = allowableBlood - previousBlood; -// Assert.assertEquals(availableBlood, row.get("BloodRemaining/availableBlood")); -// } - - //bloodDrawsByDay.sql - SelectRowsCommand select3 = new SelectRowsCommand("study", "bloodDrawsByDay"); - select3.setColumns(Arrays.asList("Id", "date", "quantity", "dropdate", "blood_draw_interval")); - select3.setSorts(Arrays.asList(sort)); - select3.addFilter(new Filter("Id", animalId, Filter.Operator.EQUAL)); - SelectRowsResponse resp3 = select3.execute(getApiHelper().getConnection(), getContainerPath()); - for (Map row : resp3.getRows()) - { - //note: some servers seem to return this as a string? - Date rowDate = (row.get("date") instanceof Date) ? (Date) row.get("date") : _df.parse(row.get("date").toString()); - Date rowDropDate = (row.get("dropdate") instanceof Date) ? (Date) row.get("dropdate") : _df.parse(row.get("dropdate").toString()); - - Calendar dropDate = Calendar.getInstance(); - dropDate.setTime(DateUtils.truncate(rowDate, Calendar.DATE)); - dropDate.add(Calendar.DATE, bloodDrawInterval); - Assert.assertEquals(dropDate.getTime(), rowDropDate); - Assert.assertEquals(bloodByDay.get(rowDate), row.get("quantity")); - Assert.assertEquals(bloodDrawInterval.doubleValue(), row.get("blood_draw_interval")); - } - - //currentBloodDraws.sql - SelectRowsCommand select4 = new SelectRowsCommand("study", "currentBloodDraws"); - select4.setColumns(Arrays.asList("Id", "date", "mostRecentWeight", "mostRecentWeightDate", "maxAllowableBlood", "bloodPrevious", "bloodFuture", "allowableFuture", "allowableBlood", "minDate", "maxDate")); - select4.setSorts(Arrays.asList(sort)); - select4.setQueryParameters(Maps.of("DATE_INTERVAL", bloodDrawInterval.toString())); - select4.addFilter(new Filter("Id", animalId, Filter.Operator.EQUAL)); - SelectRowsResponse resp4 = select4.execute(getApiHelper().getConnection(), getContainerPath()); - - for (Map row : resp4.getRows()) - { - //note: some servers seem to return this as a string? - Date rowDate = (row.get("date") instanceof Date) ? (Date) row.get("date") : _df.parse(row.get("date").toString()); - - Double lastWeight = null; - Date lastWeightDate = null; - for (Date weightDate : weightByDay.keySet()) - { - if (lastWeightDate == null || weightDate.getTime() >= lastWeightDate.getTime()) - { - lastWeightDate = weightDate; - lastWeight = weightByDay.get(weightDate); - } - } - Assert.assertEquals(lastWeight, row.get("mostRecentWeight")); - Assert.assertEquals(lastWeightDate, row.get("mostRecentWeightDate")); - - Double allowableBlood = lastWeight * bloodPerKg * maxDrawPct; - Assert.assertEquals(allowableBlood, row.get("maxAllowableBlood")); - - Double previousBlood = 0.0; - Double futureBlood = 0.0; - Calendar minDate = Calendar.getInstance(); - minDate.setTime(DateUtils.truncate(rowDate, Calendar.DATE)); - minDate.add(Calendar.DATE, -1 * bloodDrawInterval); - Assert.assertEquals(minDate.getTime(), row.get("minDate")); - - Calendar maxDate = Calendar.getInstance(); - maxDate.setTime(DateUtils.truncate(rowDate, Calendar.DATE)); - maxDate.add(Calendar.DATE, bloodDrawInterval); - Assert.assertEquals(maxDate.getTime(), row.get("maxDate")); - - for (Date bloodDate : bloodByDay.keySet()) - { - //we want any draws GTE the min date considered and LTE the row's date - if (bloodDate.getTime() > minDate.getTime().getTime() && bloodDate.getTime() <= DateUtils.truncate(rowDate, Calendar.DATE).getTime()) - { - previousBlood += bloodByDay.get(bloodDate); - } - - if (bloodDate.getTime() < maxDate.getTime().getTime() && bloodDate.getTime() >= DateUtils.truncate(rowDate, Calendar.DATE).getTime()) - { - futureBlood += bloodByDay.get(bloodDate); - } - } - Assert.assertEquals(previousBlood, row.get("bloodPrevious")); - Assert.assertEquals(futureBlood, row.get("bloodFuture")); - - Assert.assertEquals((allowableBlood - previousBlood), row.get("allowableBlood")); - Assert.assertEquals((allowableBlood - futureBlood), row.get("allowableFuture")); - } - - //demographicsBloodSummary.sql - SelectRowsCommand select5 = new SelectRowsCommand("study", "demographicsBloodSummary"); - select5.setColumns(Arrays.asList("Id", "mostRecentWeight", "mostRecentWeightDate", "availBlood", "bloodPrevious", "bloodFuture")); - select5.addFilter(new Filter("Id", animalId, Filter.Operator.EQUAL)); - SelectRowsResponse resp5 = select5.execute(getApiHelper().getConnection(), getContainerPath()); - - List dates = new ArrayList<>(weightByDay.keySet()); - Collections.sort(dates); - Date mostRecentWeightDate = dates.get(dates.size() - 1); - Double mostRecentWeight = weightByDay.get(mostRecentWeightDate); - Double allowableBlood = mostRecentWeight * bloodPerKg * maxDrawPct; -// for (Map row : resp5.getRows()) -// { -// Assert.assertEquals(mostRecentWeight, row.get("mostRecentWeight")); -// Assert.assertEquals(DateUtils.truncate(mostRecentWeightDate, Calendar.DATE), row.get("mostRecentWeightDate")); -// -// Calendar minDate = Calendar.getInstance(); -// minDate.setTime(DateUtils.truncate(new Date(), Calendar.DATE)); -// minDate.add(Calendar.DATE, -1 * bloodDrawInterval); -// -// Calendar maxDate = Calendar.getInstance(); -// maxDate.setTime(DateUtils.truncate(new Date(), Calendar.DATE)); -// maxDate.add(Calendar.DATE, bloodDrawInterval); -// -// Double previousBlood = 0.0; -// Double futureBlood = 0.0; -// for (Date bloodDate : bloodByDay.keySet()) -// { -// if (bloodDate.getTime() <= (new Date()).getTime() && bloodDate.getTime() >= minDate.getTime().getTime()) -// { -// previousBlood += bloodByDay.get(bloodDate); -// } -// -// if (bloodDate.getTime() > (new Date()).getTime() && bloodDate.getTime() < maxDate.getTime().getTime()) -// { -// futureBlood += bloodByDay.get(bloodDate); -// } -// } -// Assert.assertEquals(previousBlood, row.get("bloodPrevious")); -// Assert.assertEquals(futureBlood, row.get("bloodFuture")); -// -// Double availableBlood = allowableBlood - previousBlood; -// Assert.assertEquals(availableBlood, row.get("availBlood")); -// } - - log("checking validation errors"); - - //request that will exceed allowable - String[] bloodFields = new String[]{"Id", "date", "quantity", "QCStateLabel", "objectid", "_recordid"}; - getApiHelper().testValidationMessage(DATA_ADMIN.getEmail(), "study", "blood", bloodFields, new Object[][]{ - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval, 1), 73, EHRQCState.REQUEST_PENDING.label, generateGUID(), "recordID"} - }, Maps.of( - "quantity", Arrays.asList("ERROR: Blood volume of 73.0 (93.0 over " + bloodDrawInterval + " days) exceeds the allowable volume of " + allowableBlood + " mL (weight: " + mostRecentWeight + " kg)"), - "num_tubes", Arrays.asList("ERROR: Blood volume of 73.0 (93.0 over " + bloodDrawInterval + " days) exceeds the allowable volume of " + allowableBlood + " mL (weight: " + mostRecentWeight + " kg)") - ), Maps.of("targetQC", null)); - - //2 requests that will exceed the volume together - Double amount = 40.0; - Double warn1 = 20.0 + amount; - Double warn2 = 20.0 + amount + amount; - List expectedErrors = new ArrayList<>(); - expectedErrors.add("ERROR: Blood volume of 40.0 (" + warn2 + " over " + bloodDrawInterval + " days) exceeds the allowable volume of " + allowableBlood + " mL (weight: " + mostRecentWeight + " kg)"); - if (warn1 > allowableBlood) - { - expectedErrors.add("ERROR: Blood volume of 40.0 (" + warn1 + " over " + bloodDrawInterval + " days) exceeds the allowable volume of " + allowableBlood + " mL (weight: " + mostRecentWeight + " kg)"); - } - - getApiHelper().testValidationMessage(DATA_ADMIN.getEmail(), "study", "blood", bloodFields, new Object[][]{ - {animalId, _tf.format(prepareDate(startCal.getTime(), bloodDrawInterval, 1)), amount, EHRQCState.REQUEST_PENDING.label, generateGUID(), "recordID"}, - {animalId,_tf.format(prepareDate(startCal.getTime(), bloodDrawInterval, 1)), amount, EHRQCState.REQUEST_PENDING.label, generateGUID(), "recordID2"} - }, Maps.of( - "quantity", expectedErrors, - "num_tubes", expectedErrors - ), Maps.of("targetQC", null)); - - //use different date, which triggers different weight - Map additionalExtraContext = new HashMap<>(); - JSONObject weightInTransaction = new JSONObject(); - Double newWeight = 2.0; - Double newAllowableBlood = newWeight * bloodPerKg * maxDrawPct; - weightInTransaction.put(animalId, Arrays.asList(Maps.of("objectid", generateGUID(), "date", _tf.format(prepareDate(startCal.getTime(), bloodDrawInterval, 2)), "weight", newWeight))); - additionalExtraContext.put("weightInTransaction", weightInTransaction.toString()); - additionalExtraContext.put("targetQC", null); - - List expectedErrors2 = new ArrayList<>(); - expectedErrors2.add("ERROR: Blood volume of 40.0 (" + warn2 + " over " + bloodDrawInterval + " days) exceeds the allowable volume of " + newAllowableBlood + " mL (weight: " + newWeight + " kg)"); - if (warn1 > newAllowableBlood) - { - expectedErrors2.add("ERROR: Blood volume of 40.0 (" + warn1 + " over " + bloodDrawInterval + " days) exceeds the allowable volume of " + newAllowableBlood + " mL (weight: " + newWeight + " kg)"); - } - - getApiHelper().testValidationMessage(DATA_ADMIN.getEmail(), "study", "blood", bloodFields, new Object[][]{ - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval, 1), amount, EHRQCState.REQUEST_PENDING.label, generateGUID(), "recordID"}, - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval, 1), amount, EHRQCState.REQUEST_PENDING.label, generateGUID(), "recordID2"} - }, Maps.of( - "quantity", expectedErrors2, - "num_tubes", expectedErrors2 - ), additionalExtraContext); - - // try request right on date borders - getApiHelper().testValidationMessage(DATA_ADMIN.getEmail(), "study", "blood", bloodFields, new Object[][]{ - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval * 2, 1), 70.5, EHRQCState.COMPLETED.label, generateGUID(), "recordID"} - }, Maps.of( - "quantity", Arrays.asList( - "INFO: Blood volume of 70.5 (74.5 over " + bloodDrawInterval + " days) exceeds the allowable volume of " + allowableBlood + " mL (weight: " + mostRecentWeight + " kg)" - ), - "num_tubes", Arrays.asList( - "INFO: Blood volume of 70.5 (74.5 over " + bloodDrawInterval + " days) exceeds the allowable volume of " + allowableBlood + " mL (weight: " + mostRecentWeight + " kg)" - ), - "date", Arrays.asList("INFO: Date is in the future") - ), Maps.of("targetQC", null)); - - // this should fail - getApiHelper().testValidationMessage(DATA_ADMIN.getEmail(), "study", "blood", bloodFields, new Object[][]{ - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval * 2, 1), (allowableBlood - 5), EHRQCState.REQUEST_PENDING.label, generateGUID(), "recordID"} - }, Collections.emptyMap()); - - // advance one day and it should succeed, showing the draw drops off correctly - getApiHelper().testValidationMessage(DATA_ADMIN.getEmail(), "study", "blood", bloodFields, new Object[][]{ - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval * 2 + 1, 1), (allowableBlood - 5), EHRQCState.REQUEST_PENDING.label, generateGUID(), "recordID"} - }, Collections.emptyMap()); - - //insert record between two existing records. this record will itself be valid in either direction over the window; however, it will invalidate the previous draw - Map newRow = new HashMap<>(); - newRow.put("Id", animalId); - newRow.put("date", prepareDate(startCal.getTime(), bloodDrawInterval + bloodDrawInterval - 2, 4)); - newRow.put("quantity", 2); - newRow.put("QCStateLabel", EHRQCState.REQUEST_APPROVED.label); - newRow.put("objectid", generateGUID()); - newRow.put("recordid", "recordID"); - - getApiHelper().insertRow("study", "blood", newRow, false); - - Map newRow2 = new HashMap<>(); - newRow2.put("Id", animalId); - newRow2.put("date", prepareDate(startCal.getTime(), bloodDrawInterval + bloodDrawInterval + 2, 4)); - newRow2.put("quantity", 6); - newRow2.put("QCStateLabel", EHRQCState.REQUEST_APPROVED.label); - newRow2.put("objectid", generateGUID()); - newRow2.put("recordid", "recordID"); - - getApiHelper().insertRow("study", "blood", newRow2, false); - getApiHelper().testValidationMessage(DATA_ADMIN.getEmail(), "study", "blood", bloodFields, new Object[][]{ - {animalId, prepareDate(startCal.getTime(), bloodDrawInterval + bloodDrawInterval, 4), 62.0, EHRQCState.REQUEST_APPROVED.label, generateGUID(), "recordID"} - }, Maps.of( - "quantity", Arrays.asList( - "ERROR: Blood volume of 62.0 (74.0 over " + bloodDrawInterval + " days) exceeds the allowable volume of " + allowableBlood + " mL (weight: " + mostRecentWeight + " kg)" - ), - "num_tubes", Arrays.asList( - "ERROR: Blood volume of 62.0 (74.0 over " + bloodDrawInterval + " days) exceeds the allowable volume of " + allowableBlood + " mL (weight: " + mostRecentWeight + " kg)" - ) - ), Maps.of("targetQC", null)); - } - private Pair generateProtocolAndProject() throws Exception { //create project - String protocolTitle = generateGUID(); + String protocolTitle = generateGUID(); InsertRowsCommand protocolCommand = new InsertRowsCommand("ehr", "protocol"); protocolCommand.addRow(Maps.of("protocol", null, "title", protocolTitle)); protocolCommand.execute(getApiHelper().getConnection(), getContainerPath()); @@ -757,7 +358,7 @@ public void testProjectProtocolApi() throws Exception {null, projectName} }, Maps.of( "name", Arrays.asList( - "ERROR: There is already a project with the name: " + projectName + "ERROR: There is already an old project with the name in ehr: " + projectName ) )); } @@ -835,14 +436,21 @@ public void testArrivalApi() throws Exception String quarrantineFlagId = ensureFlagExists("Surveillance", "Quarantine", null); String nonRestrictedFlagId = ensureFlagExists("Condition", "Nonrestricted", null); + log("Get AcquistionType rowid"); + SelectRowsCommand acquisitionTypeCmd = new SelectRowsCommand("ehr_lookups", "AcquistionType"); + acquisitionTypeCmd.setColumns(Arrays.asList("rowid", "value")); + acquisitionTypeCmd.addFilter(new Filter("value", "Acquired")); + Map acquisitionTypeResult= acquisitionTypeCmd.execute(getApiHelper().getConnection(), getContainerPath()).getRows().get(0); + Integer acqType = (Integer) acquisitionTypeResult.get("rowid"); + //insert into arrival log("Creating Ids"); Date birth = new Date(); Date arrivalDate = prepareDate(new Date(), -3, 0); getApiHelper().doSaveRows(DATA_ADMIN.getEmail(), getApiHelper().prepareInsertCommand("study", "arrival", "lsid", - new String[]{"Id", "Date", "gender", "species", "geographic_origin", "birth", "initialRoom", "initialCage", "QCStateLabel"}, + new String[]{"Id", "Date", "gender", "species", "geographic_origin", "birth", "initialRoom", "initialCage", "QCStateLabel", "acquisitionType"}, new Object[][]{ - {arrivalId1, arrivalDate, "f", RHESUS, INDIAN, birth, ROOMS[0], CAGES[0], EHRQCState.COMPLETED.label} + {arrivalId1, arrivalDate, "f", RHESUS, INDIAN, birth, ROOMS[0], CAGES[0], EHRQCState.COMPLETED.label, acqType} } ), getExtraContext()); @@ -1659,7 +1267,7 @@ public void testNotifications() //iterate all notifications and run them. log("running all notifications"); - List skippedNotifications = Arrays.asList("ETL Validation Notification"); + List skippedNotifications = Arrays.asList("ETL Validation Notification", "Billing Validation Notification", "Pregnant NHPs Gestation Notification"); //Skip "Billing Validation Notification" - this is broken on the server and not been run successfully by the client. int count = Locator.tagContainingText("a", "Run Report In Browser").findElements(getDriver()).size(); for (int i = 0; i < count; i++) @@ -2162,7 +1770,7 @@ public void testClinicalHistoryPanelOptions(){ } @Test - public void testNecropsyRequestFlow() + public void testNecropsyRequestFlow() throws IOException, CommandException { String animalId = "12345"; LocalDateTime now = LocalDateTime.now(); @@ -2173,6 +1781,11 @@ public void testNecropsyRequestFlow() DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String tissue = "AMNION (T-88300)"; + // Insert a row so we can select a charge unit in the form + InsertRowsCommand protocolCommand = new InsertRowsCommand("onprc_billing", "chargeUnits"); + protocolCommand.addRow(Maps.of("chargetype", "ChargeUnit1", "servicecenter", "ServiceCenter1", "shownInProcedures", true, "active", true)); + protocolCommand.execute(getApiHelper().getConnection(), getContainerPath()); + log("Begin the test with entry data page"); EnterDataPage enterData = EnterDataPage.beginAt(this, getContainerPath()); enterData.waitAndClickAndWait(Locator.linkWithText("Necropsy Request")); @@ -2187,6 +1800,7 @@ public void testNecropsyRequestFlow() clickButton("Submit",0); _ext4Helper.selectComboBoxItem("Type:", Ext4Helper.TextMatchTechnique.CONTAINS,type); setNecropsYFormElement("chargetype", chargeType); + _ext4Helper.selectComboBoxItem("Charge Unit:", Ext4Helper.TextMatchTechnique.CONTAINS, "ChargeUnit1"); _ext4Helper.selectComboBoxItem("Procedure:", Ext4Helper.TextMatchTechnique.CONTAINS, procedureid); LocalDateTime tomorrow = now.plus(1, ChronoUnit.DAYS); diff --git a/ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest2.java b/ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest2.java index 990a3c91b..850f880b3 100644 --- a/ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest2.java +++ b/ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest2.java @@ -37,6 +37,7 @@ import org.labkey.test.util.LogMethod; import org.labkey.test.util.Maps; import org.labkey.test.util.PasswordUtil; +import org.labkey.test.util.SchemaHelper; import org.labkey.test.util.ext4cmp.Ext4CmpRef; import org.labkey.test.util.ext4cmp.Ext4ComboRef; import org.labkey.test.util.ext4cmp.Ext4FieldRef; @@ -500,7 +501,7 @@ public void testArrivalForm() throws Exception { _helper.goToTaskForm("Arrival", "Submit Final", false); - waitAndClick(Ext4Helper.Locators.ext4Button("Lock Entry")); + waitAndClick(Ext4Helper.Locators.ext4Button("Enable the form for data entry")); waitForElement(Ext4Helper.Locators.ext4Button("Submit Final"), WAIT_FOR_PAGE * 2); _ext4Helper.queryOne("button[text='Submit Final']", Ext4CmpRef.class).waitForEnabled(); @@ -535,6 +536,13 @@ public void testArrivalForm() throws Exception sourceField.waitForStoreLoad(); sourceField.setComboByDisplayValue(source); + String acquisitionType = "Acquired"; + _helper.toggleBulkEditField("Acquisition Type"); + + Ext4ComboRef acquisitionTypeField = _ext4Helper.queryOne("window field[fieldLabel='Acquisition Type']", Ext4ComboRef.class); + acquisitionTypeField.waitForStoreLoad(); + acquisitionTypeField.setComboByDisplayValue(acquisitionType); + String gender = "female"; _helper.toggleBulkEditField("Gender"); _ext4Helper.queryOne("window field[fieldLabel=Gender]", Ext4ComboRef.class).setComboByDisplayValue(gender); @@ -572,12 +580,16 @@ public void testArrivalForm() throws Exception waitAndClick(_helper.getDataEntryButton("Submit Final")); waitForElement(Ext4Helper.Locators.window("Finalize Birth/Arrival Form")); - waitAndClick(WAIT_FOR_JAVASCRIPT, Ext4Helper.Locators.window("Finalize Birth/Arrival Form").append(Ext4Helper.Locators.ext4Button("Yes")), WAIT_FOR_PAGE * 2); + Locator finalizeOKButton = Ext4Helper.Locators.window("Finalize Birth/Arrival Form").append(Ext4Helper.Locators.ext4Button("Yes")); + waitForElement(finalizeOKButton, WAIT_FOR_JAVASCRIPT); + click(finalizeOKButton); + + waitAndClick(WAIT_FOR_JAVASCRIPT * 2, Ext4Helper.Locators.window("Success").append(Ext4Helper.Locators.ext4Button("No")), WAIT_FOR_PAGE); waitForElement(Locator.tagWithText("a", "Enter New Data")); _helper.goToTaskForm("Arrival", "Submit Final", false); - waitAndClick(Ext4Helper.Locators.ext4Button("Lock Entry")); + waitAndClick(Ext4Helper.Locators.ext4Button("Enable the form for data entry")); waitForElement(Ext4Helper.Locators.ext4Button("Submit Final"), WAIT_FOR_PAGE * 2); _ext4Helper.queryOne("button[text='Submit Final']", Ext4CmpRef.class).waitForEnabled();