From d6a56b6a5ddf16d00e6febb015d163129b2bf2f5 Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Wed, 11 Sep 2024 18:48:39 -0700 Subject: [PATCH 1/5] Bulk medication treatment and performed by refactor (#381) * Add bulk medication button and window to treatment schedule * HTML encode drug history provider * Refactor "ordered by" to not use "performed by" column * Move performed by fk entirely to table customizer and remove from form metadata --- .../queries/study/assignment.query.xml | 4 +- .../study/clinical_observations.query.xml | 3 + .../resources/queries/study/deaths.query.xml | 9 +- .../resources/queries/study/drug.query.xml | 5 +- .../resources/queries/study/drug/.qview.xml | 1 + .../resources/queries/study/flags.query.xml | 4 +- .../resources/queries/study/housing.query.xml | 4 +- .../queries/study/necropsy.query.xml | 9 +- .../study/protocolAssignment.query.xml | 4 +- .../queries/study/treatmentSchedule.query.xml | 10 ++ .../queries/study/treatmentSchedule.sql | 3 +- .../queries/study/treatment_order.query.xml | 4 +- .../queries/study/treatment_order/.qview.xml | 2 +- .../resources/queries/study/weight.query.xml | 4 +- .../study/datasets/datasets_metadata.xml | 8 + .../postgresql/nirc_ehr-24.012-24.013.sql | 1 + .../nirc_ehr/buttons/RecordTreatmentButton.js | 150 ++++++++++++++++++ .../model/sources/ClinicalDefaults.js | 95 +---------- .../nirc_ehr/model/sources/DeathNecropsy.js | 27 +--- .../web/nirc_ehr/model/sources/NIRCDefault.js | 142 ++++++----------- .../org/labkey/nirc_ehr/NIRC_EHRModule.java | 2 +- .../nirc_ehr/history/DrugAdminDataSource.java | 5 +- .../nirc_ehr/table/NIRC_EHRCustomizer.java | 27 ++-- .../tests.nirc_ehr/NIRC_EHRTest.java | 2 +- 24 files changed, 255 insertions(+), 270 deletions(-) create mode 100644 nirc_ehr/resources/schemas/dbscripts/postgresql/nirc_ehr-24.012-24.013.sql create mode 100644 nirc_ehr/resources/web/nirc_ehr/buttons/RecordTreatmentButton.js diff --git a/nirc_ehr/resources/queries/study/assignment.query.xml b/nirc_ehr/resources/queries/study/assignment.query.xml index 45785fbe..1cf7a369 100644 --- a/nirc_ehr/resources/queries/study/assignment.query.xml +++ b/nirc_ehr/resources/queries/study/assignment.query.xml @@ -17,9 +17,7 @@ - - Performed By - + true diff --git a/nirc_ehr/resources/queries/study/clinical_observations.query.xml b/nirc_ehr/resources/queries/study/clinical_observations.query.xml index d97da950..3088238c 100644 --- a/nirc_ehr/resources/queries/study/clinical_observations.query.xml +++ b/nirc_ehr/resources/queries/study/clinical_observations.query.xml @@ -36,6 +36,9 @@ Performed By false + + Scheduled Date + diff --git a/nirc_ehr/resources/queries/study/deaths.query.xml b/nirc_ehr/resources/queries/study/deaths.query.xml index b24a814f..efa2b558 100644 --- a/nirc_ehr/resources/queries/study/deaths.query.xml +++ b/nirc_ehr/resources/queries/study/deaths.query.xml @@ -18,14 +18,7 @@ - - - core - Users - UserId - DisplayName - - + true diff --git a/nirc_ehr/resources/queries/study/drug.query.xml b/nirc_ehr/resources/queries/study/drug.query.xml index 3da5bc50..8eff4fb4 100644 --- a/nirc_ehr/resources/queries/study/drug.query.xml +++ b/nirc_ehr/resources/queries/study/drug.query.xml @@ -90,9 +90,8 @@ - - Ordered By - + + Scheduled Date diff --git a/nirc_ehr/resources/queries/study/drug/.qview.xml b/nirc_ehr/resources/queries/study/drug/.qview.xml index 504d2447..7c9d6eb1 100644 --- a/nirc_ehr/resources/queries/study/drug/.qview.xml +++ b/nirc_ehr/resources/queries/study/drug/.qview.xml @@ -17,6 +17,7 @@ + diff --git a/nirc_ehr/resources/queries/study/flags.query.xml b/nirc_ehr/resources/queries/study/flags.query.xml index 2d1b19ae..b5039908 100644 --- a/nirc_ehr/resources/queries/study/flags.query.xml +++ b/nirc_ehr/resources/queries/study/flags.query.xml @@ -32,9 +32,7 @@ true - - Performed By - + true diff --git a/nirc_ehr/resources/queries/study/housing.query.xml b/nirc_ehr/resources/queries/study/housing.query.xml index 0f0f682e..281899e0 100644 --- a/nirc_ehr/resources/queries/study/housing.query.xml +++ b/nirc_ehr/resources/queries/study/housing.query.xml @@ -43,9 +43,7 @@ - - Performed By - + diff --git a/nirc_ehr/resources/queries/study/necropsy.query.xml b/nirc_ehr/resources/queries/study/necropsy.query.xml index 7e990d50..73cd38fd 100644 --- a/nirc_ehr/resources/queries/study/necropsy.query.xml +++ b/nirc_ehr/resources/queries/study/necropsy.query.xml @@ -43,14 +43,7 @@ true - - - core - Users - userId - DisplayName - - + true diff --git a/nirc_ehr/resources/queries/study/protocolAssignment.query.xml b/nirc_ehr/resources/queries/study/protocolAssignment.query.xml index 96fee360..ac61d1cd 100644 --- a/nirc_ehr/resources/queries/study/protocolAssignment.query.xml +++ b/nirc_ehr/resources/queries/study/protocolAssignment.query.xml @@ -19,9 +19,7 @@ - - Performed By - + true diff --git a/nirc_ehr/resources/queries/study/treatmentSchedule.query.xml b/nirc_ehr/resources/queries/study/treatmentSchedule.query.xml index 4a1c5cba..d6fd5746 100644 --- a/nirc_ehr/resources/queries/study/treatmentSchedule.query.xml +++ b/nirc_ehr/resources/queries/study/treatmentSchedule.query.xml @@ -9,6 +9,10 @@ true + + true + true + true @@ -145,6 +149,7 @@ ehr.context /ehr/studyButtons.js + nirc_ehr/buttons/RecordTreatmentButton.js EHR.DatasetButtons.moreActionsHandler Grid Views @@ -156,6 +161,11 @@ Print + + + NIRC_EHR.RecordTreatmentButton.recordTreatmentsHandler(dataRegion); + + EHR.DatasetButtons.historyHandler(dataRegion, dataRegionName); diff --git a/nirc_ehr/resources/queries/study/treatmentSchedule.sql b/nirc_ehr/resources/queries/study/treatmentSchedule.sql index d7fce10b..acd0f38f 100644 --- a/nirc_ehr/resources/queries/study/treatmentSchedule.sql +++ b/nirc_ehr/resources/queries/study/treatmentSchedule.sql @@ -9,7 +9,8 @@ d.id, d.calculated_status, s.*, s.objectid as treatmentid, -drug.qcstate.label as treatmentStatus +drug.qcstate.label as treatmentStatus, +s.objectid || '-pkSeparator-' || s.date as primaryKey -- -pkSeparator- is used to separate the two parts of the primary key in RecordTreatmentButton.js FROM study.demographics d JOIN diff --git a/nirc_ehr/resources/queries/study/treatment_order.query.xml b/nirc_ehr/resources/queries/study/treatment_order.query.xml index 32070788..5648b5a7 100644 --- a/nirc_ehr/resources/queries/study/treatment_order.query.xml +++ b/nirc_ehr/resources/queries/study/treatment_order.query.xml @@ -115,8 +115,10 @@ + true + + false - Ordered By Parent ID diff --git a/nirc_ehr/resources/queries/study/treatment_order/.qview.xml b/nirc_ehr/resources/queries/study/treatment_order/.qview.xml index 0ca86edf..7bc70276 100644 --- a/nirc_ehr/resources/queries/study/treatment_order/.qview.xml +++ b/nirc_ehr/resources/queries/study/treatment_order/.qview.xml @@ -19,7 +19,7 @@ - + diff --git a/nirc_ehr/resources/queries/study/weight.query.xml b/nirc_ehr/resources/queries/study/weight.query.xml index e7e76d15..d9ee743d 100644 --- a/nirc_ehr/resources/queries/study/weight.query.xml +++ b/nirc_ehr/resources/queries/study/weight.query.xml @@ -28,9 +28,7 @@ - - Performed By - + diff --git a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml index 239051e8..be1809e1 100644 --- a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml +++ b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml @@ -1025,6 +1025,10 @@ varchar + + Ordered By + varchar + @@ -1158,6 +1162,10 @@ varcharurn:ehr.labkey.org/#CaseId + + Ordered By + varchar +
diff --git a/nirc_ehr/resources/schemas/dbscripts/postgresql/nirc_ehr-24.012-24.013.sql b/nirc_ehr/resources/schemas/dbscripts/postgresql/nirc_ehr-24.012-24.013.sql new file mode 100644 index 00000000..b1347bc1 --- /dev/null +++ b/nirc_ehr/resources/schemas/dbscripts/postgresql/nirc_ehr-24.012-24.013.sql @@ -0,0 +1 @@ +SELECT core.executeJavaUpgradeCode('reloadFolder'); \ No newline at end of file diff --git a/nirc_ehr/resources/web/nirc_ehr/buttons/RecordTreatmentButton.js b/nirc_ehr/resources/web/nirc_ehr/buttons/RecordTreatmentButton.js new file mode 100644 index 00000000..ee2b85fa --- /dev/null +++ b/nirc_ehr/resources/web/nirc_ehr/buttons/RecordTreatmentButton.js @@ -0,0 +1,150 @@ +Ext4.namespace('NIRC_EHR.RecordTreatmentButton'); + +Ext4.define('NIRC_EHR.window.RecordTreatmentWindow', { + extend: 'Ext.window.Window', + + initComponent: function() { + Ext4.apply(this, { + title: 'Record Treatments', + modal: true, + width: 450, + bodyStyle: 'padding: 5px;', + closeAction: 'destroy', + items: [{ + xtype: 'labkey-combo', + fieldLabel: 'Performed By', + width: 350, + labelWidth: 100, + value: LABKEY.Security.currentUser.id, + itemId: 'performedBy', + displayField: 'DisplayName', + valueField: 'UserId', + queryMode: 'local', + forceSelection: true, + matchFieldWidth: false, + store: { + type: 'labkey-store', + schemaName: 'core', + queryName: 'PrincipalsWithoutAdmin', + columns: 'UserId,DisplayName,FirstName,LastName', + sort: 'Type,DisplayName', + autoLoad: true + }, + anyMatch: true, + caseSensitive: false, + }, { + xtype: 'xdatetime', + itemId: 'dateField', + width: 350, + labelWidth: 100, + fieldLabel: 'Date', + allowBlank: false, + name: 'date', + value: new Date() + },], + buttons: [{ + text:'Submit', + scope: this, + handler: function (btn) { + this.recordTreatment(btn, this.dataRegion); + } + },{ + text: 'Cancel', + scope: this, + handler: function(btn){ + btn.up('window').close(); + } + }] + }); + + this.callParent(arguments); + }, + + recordTreatment: function(btn, dataRegion) { + let win = btn.up('window'); + let windDate = win.down('#dateField').getValue(); + let performedBy = win.down('#performedBy').getValue(); + const selectedRows = dataRegion.getChecked(); + dataRegion.clearSelected(); + const objectIds = selectedRows.map(row => row.split('-pkSeparator-')[0]); + LABKEY.Query.selectRows({ + schemaName: 'study', + queryName: 'treatment_order', + filterArray: [LABKEY.Filter.create('objectid', objectIds.join(';'), LABKEY.Filter.Types.EQUALS_ONE_OF)], + scope: this, + columns: 'Id,objectid,code,reason,route,amount,amount_units,concentration,volume,vol_units,conc_units,dosage,dosage_units', + success: function (data) { + let rowsToInsert = []; + Ext4.each(data.rows, function(row) { + let scheduledDate; + Ext4.each(selectedRows, function(selectedRow) { + const parts = selectedRow.split('-pkSeparator-'); + const objectId = parts[0]; + const date = parts[1]; + if (row.objectid === objectId) { + scheduledDate = date; + rowsToInsert.push({ + Id: row.Id, + treatmentid: row.objectid, + date: windDate, + performedby: performedBy, + objectid: LABKEY.Utils.generateUUID(), + scheduledDate: scheduledDate, + code: row.code, + reason: row.reason, + route: row.route, + amount: row.amount, + amount_units: row.amount_units, + concentration: row.concentration, + conc_units: row.conc_units, + dosage: row.dosage, + dosage_units: row.dosage_units, + volume: row.volume, + vol_units: row.vol_units, + outcome: 'Normal' + }); + } + }); + }); + + LABKEY.Query.insertRows({ + schemaName: 'study', + queryName: 'drug', + rows: rowsToInsert, + scope: this, + success: function() { + Ext4.Msg.alert('Success', 'Treatments recorded successfully.', function(){ + window.location = LABKEY.ActionURL.buildURL('ehr', 'animalHistory') + '#inputType:none&showReport:0&activeReport:clinMedicationSchedule'; + window.location.reload(); + }); + win.close(); + }, + failure: function(error) { + Ext4.Msg.alert('Error', 'An error occurred while recording treatments.'); + console.error(error); + } + }); + }, + failure: function(error) { + Ext4.Msg.alert('Error', 'An error occurred querying treatments.'); + console.error(error); + } + }); + } + +}); + +NIRC_EHR.RecordTreatmentButton = new function () { + return { + recordTreatmentsHandler: function(dataRegion) { + if (dataRegion && dataRegion.getChecked().length > 0) { + Ext4.create('NIRC_EHR.window.RecordTreatmentWindow', { + dataRegion: dataRegion + }).show(); + } + else { + Ext4.Msg.alert('Error', 'Please select at least one treatment.'); + } + }, + } +} diff --git a/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalDefaults.js b/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalDefaults.js index 40d6119c..bca28ddd 100644 --- a/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalDefaults.js +++ b/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalDefaults.js @@ -11,33 +11,14 @@ EHR.model.DataModelManager.registerMetadata('ClinicalDefaults', { hidden: true }, performedby: { - hidden: false, - allowBlank: false, - defaultValue: null, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'veterinarians', - keyColumn: 'UserId', - displayColumn: 'DisplayName' - } - }, + hidden: true + } }, 'study.drug': { category: { defaultValue: 'Clinical', hidden: true }, - performedby: { - hidden: false, - allowBlank: false, - defaultValue: null, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'veterinarians', - keyColumn: 'UserId', - displayColumn: 'DisplayName' - } - }, scheduledDate: { columnConfig: { width: 130, @@ -65,46 +46,12 @@ EHR.model.DataModelManager.registerMetadata('ClinicalDefaults', { defaultValue: 'Clinical', hidden: true, allowBlank: false - }, - performedby: { - hidden: false, - defaultValue: LABKEY.Security.currentUser.id.toString(), - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - - // 'performedby' is a text field in the dataset and its lookup to the userid is an int field - this mismatch causes it to disappear - // from the display when a value is selected from the dropdown even though the 'userid' value gets saved as a text (this behavior was only seen - // in the form panel but not in the grid panel). - // casting it as a varchar when loading the store fixes this issue. - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - } } }, 'study.blood': { reason: { defaultValue: 'Clinical', hidden: true - }, - performedby: { - hidden: false, - defaultValue: LABKEY.Security.currentUser.id.toString(), - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - - // 'performedby' is a text field in the dataset and its lookup to the userid is an int field - this mismatch causes it to disappear - // from the display when a value is selected from the dropdown even though the 'userid' value gets saved as a text (this behavior was only seen - // in the form panel but not in the grid panel). - // casting it as a varchar when loading the store fixes this issue. - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - } } }, 'study.cases': { @@ -135,18 +82,6 @@ EHR.model.DataModelManager.registerMetadata('ClinicalDefaults', { caseCategory: { hidden: true }, - performedby: { - hidden: false, - defaultValue: LABKEY.Security.currentUser.id.toString(), - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - } - }, formCasesLink: { xtype: 'nirc_ehr-editCases' } @@ -177,18 +112,6 @@ EHR.model.DataModelManager.registerMetadata('ClinicalDefaults', { editable: false } }, - performedby: { - hidden: false, - defaultValue: LABKEY.Security.currentUser.id.toString(), - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - } - }, enddate: { hidden: true }, @@ -199,20 +122,6 @@ EHR.model.DataModelManager.registerMetadata('ClinicalDefaults', { hidden: true }, }, - 'study.clinical_observations': { - performedby: { - hidden: false, - defaultValue: LABKEY.Security.currentUser.id.toString(), - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - } - } - }, 'study.vitals': { category: { defaultValue: 'Clinical', diff --git a/nirc_ehr/resources/web/nirc_ehr/model/sources/DeathNecropsy.js b/nirc_ehr/resources/web/nirc_ehr/model/sources/DeathNecropsy.js index 7cc65a93..4be79f4c 100644 --- a/nirc_ehr/resources/web/nirc_ehr/model/sources/DeathNecropsy.js +++ b/nirc_ehr/resources/web/nirc_ehr/model/sources/DeathNecropsy.js @@ -12,34 +12,9 @@ EHR.model.DataModelManager.registerMetadata('DeathNecropsy', { dateFormat: 'Y-m-d', timeFormat: 'H:i' }, - }, - performedby: { - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - }, - defaultValue: LABKEY.Security.currentUser.id.toString(), - allowBlank: false - }, + } }, 'study.necropsy': { - performedby: { - hidden: false, - allowBlank: true, - defaultValue: LABKEY.Security.currentUser.id.toString(), - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - } - }, necropsyWeight: { label: 'Weight (kg)' }, diff --git a/nirc_ehr/resources/web/nirc_ehr/model/sources/NIRCDefault.js b/nirc_ehr/resources/web/nirc_ehr/model/sources/NIRCDefault.js index 3fda852e..1e31627b 100644 --- a/nirc_ehr/resources/web/nirc_ehr/model/sources/NIRCDefault.js +++ b/nirc_ehr/resources/web/nirc_ehr/model/sources/NIRCDefault.js @@ -10,48 +10,46 @@ EHR.model.DataModelManager.registerMetadata('Default', { xtype: 'ehr-animalIdUpperField', }, performedby: { - allowBlank: true, - nullable: true, + hidden: false, defaultValue: LABKEY.Security.currentUser.id.toString(), + getInitialValue: function (v, rec) { + return LABKEY.Security.currentUser.id; + }, editorConfig: { - xtype: 'combo', - displayField: 'DisplayName', - valueField: 'UserId', - forceSelection: true, - listConfig: { - innerTpl: '{[LABKEY.Utils.encodeHtml(values.DisplayName + (values.LastName ? " (" + values.LastName + (values.FirstName ? ", " + values.FirstName : "") + ")" : ""))]}', - getInnerTpl: function(){ - return this.innerTpl; - } + store: { + type: 'labkey-store', + schemaName: 'core', + + // 'performedby' is a text field in the dataset and its lookup to the userid is an int field - this mismatch causes it to disappear + // from the display when a value is selected from the dropdown even though the 'userid' value gets saved as a text (this behavior was only seen + // in the form panel but not in the grid panel). + // casting it as a varchar when loading the store fixes this issue. + sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', + autoLoad: true } } - } + }, + orderedby: { + hidden: false, + allowBlank: false, + defaultValue: null, + columnConfig: { + width: 160 + } + }, + scheduleddate: { + header: 'Scheduled Date/Time', + label: 'Scheduled Date/Time', + hidden: false, + userEditable: false, + nullable: true, + columnConfig: { + width: 180 + } + }, }, byQuery: { 'study.housing': { - // having to add performedby here for housing because it is getting overridden in EHR's default.js. - performedby: { - allowBlank: false, - lookup: { - schemaName: 'core', - queryName: 'users', - keyColumn: 'UserId', - displayColumn: 'DisplayName' - }, - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - - // 'performedby' is a text field in the dataset and its lookup to the userid is an int field - this mismatch causes it to disappear - // from the display when a value is selected from the dropdown even though the 'userid' value gets saved as a text (this behavior was only seen - // in the form panel but not in the grid panel). - // casting it as a varchar when loading the store fixes this issue. - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - } - }, room: { allowBlank: true, hidden: true @@ -66,6 +64,15 @@ EHR.model.DataModelManager.registerMetadata('Default', { 'enddate': { hidden: true }, + performedby: { + allowBlank: false, + lookup: { + schemaName: 'core', + queryName: 'users', + keyColumn: 'UserId', + displayColumn: 'DisplayName', + }, + }, reason: { defaultValue: null, allowBlank: false, @@ -102,78 +109,23 @@ EHR.model.DataModelManager.registerMetadata('Default', { columnConfig: { width: 400 } - }, - performedby: { - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - }, - defaultValue: LABKEY.Security.currentUser.id.toString() - }, - }, - 'study.weight': { - performedby: { - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - }, - defaultValue: LABKEY.Security.currentUser.id.toString() - } - }, - 'study.flags': { - performedby: { - editorConfig: { - store: { - type: 'labkey-store', - schemaName: 'core', - sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', - autoLoad: true - } - }, - defaultValue: LABKEY.Security.currentUser.id.toString() } }, 'study.treatment_order': { category: { defaultValue: 'Clinical', hidden: true - }, - performedby: { - hidden: false, - allowBlank: false, - defaultValue: null, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'veterinarians', - keyColumn: 'UserId', - displayColumn: 'DisplayName' - } - }, + } }, 'study.drug': { category: { defaultValue: 'Clinical', hidden: true }, - performedby: { - hidden: false, - allowBlank: false, - defaultValue: null, - lookup: { - schemaName: 'ehr_lookups', - queryName: 'veterinarians', - keyColumn: 'UserId', - displayColumn: 'DisplayName' - } - } + treatmentid: { + hidden: true, + nullable: true + }, }, } }); \ No newline at end of file diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java b/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java index ef7ba95e..8d6df46e 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java @@ -69,7 +69,7 @@ public String getName() @Override public @Nullable Double getSchemaVersion() { - return 24.012; + return 24.013; } @Override diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/history/DrugAdminDataSource.java b/nirc_ehr/src/org/labkey/nirc_ehr/history/DrugAdminDataSource.java index 6b5f667b..66a143a7 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/history/DrugAdminDataSource.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/history/DrugAdminDataSource.java @@ -5,6 +5,7 @@ import org.labkey.api.ehr.history.AbstractDataSource; import org.labkey.api.module.Module; import org.labkey.api.query.FieldKey; +import org.labkey.api.util.PageFlowUtil; import java.sql.SQLException; @@ -40,9 +41,9 @@ protected String getHtml(Container c, Results rs, boolean redacted) throws SQLEx private void addRow(StringBuilder sb, String displayLabel, String value) { - sb.append(displayLabel); + sb.append(PageFlowUtil.filter(displayLabel)); sb.append(": "); - sb.append(value); + sb.append(PageFlowUtil.filter(value)); sb.append(" "); } } diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/table/NIRC_EHRCustomizer.java b/nirc_ehr/src/org/labkey/nirc_ehr/table/NIRC_EHRCustomizer.java index 76a5ff75..48641bfb 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/table/NIRC_EHRCustomizer.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/table/NIRC_EHRCustomizer.java @@ -671,8 +671,19 @@ public void doSharedCustomization(AbstractTableInfo ti) } if ("performedby".equalsIgnoreCase(col.getName())) { - if (ti.getName().equalsIgnoreCase("treatment_order") || ti.getName().equalsIgnoreCase("drug")) + col.setLabel("Performed By"); + + UserSchema us = getEHRUserSchema(ti, "core"); + if (us != null) { + col.setFk(new QueryForeignKey(QueryForeignKey.from(us, ti.getContainerFilter()) + .table("users") + .key("UserId") + .display("DisplayName"))); + } + } + if ("orderedby".equalsIgnoreCase(col.getName())) + { col.setLabel("Ordered By"); UserSchema us = getEHRUserSchema(ti, "ehr_lookups"); if (us != null) @@ -682,20 +693,6 @@ public void doSharedCustomization(AbstractTableInfo ti) .key("UserId") .display("DisplayName"))); } - } - else - { - col.setLabel("Performed By"); - - UserSchema us = getEHRUserSchema(ti, "core"); - if (us != null) - { - col.setFk(new QueryForeignKey(QueryForeignKey.from(us, ti.getContainerFilter()) - .table("users") - .key("UserId") - .display("DisplayName"))); - } - } } if ("taskid".equalsIgnoreCase(col.getName())) { diff --git a/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java b/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java index 37e9394f..5e28137a 100644 --- a/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java +++ b/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java @@ -606,7 +606,7 @@ public void testClinicalCasesWorkflow() //Fill out Clinical Case section with Id, Date, Open Remark setFormElement(Locator.textarea("openRemark"), "Clinical Case WorkFlow - Test"); - setFormElement(Locator.textarea("p"), "Case plan"); + setFormElement(Locator.textarea("plan"), "Case plan"); setFormElement(Locator.name("Id"), animalId); setFormElement(Locator.name("date"), LocalDateTime.now().minusDays(6).format(_dateFormat)); Assert.assertEquals("Performed by is incorrect ", "vet tech fs", getFormElement(Locator.name("performedby"))); From 622a3c0cd74fbb38cdc52453d14fdc7eb66979e6 Mon Sep 17 00:00:00 2001 From: Marty Pradere Date: Fri, 13 Sep 2024 19:17:24 -0700 Subject: [PATCH 2/5] Daily Clinical Observations (#385) * Observation orders dataset * Observation order form section created and added to cases form types * Automatically create required clinical observation orders on case creation. * Merge required and additional clinical observation orders. * Clinical observation schedule query and report * Clinical observation link to record observations * Load observations in cases and observations forms from URL params * Propagate observations to all observation orders --- nirc_ehr/resources/queries/study/cases.js | 26 ++ .../queries/study/clinical_observations.js | 56 ++--- .../study/clinical_observations.query.xml | 4 + .../study/observationSchedule.query.xml | 22 ++ .../queries/study/observationSchedule.sql | 111 ++++++++ .../study/observationSchedule/.qview.xml | 17 ++ .../queries/study/observation_order.js | 1 + .../queries/study/observation_order.query.xml | 45 ++++ .../study/observation_order/.qview.xml | 17 ++ .../observation_order/Active Orders.qview.xml | 20 ++ .../study/datasets/datasets_manifest.xml | 1 + .../study/datasets/datasets_metadata.xml | 46 ++++ .../resources/reports/additionalReports.tsv | 3 + nirc_ehr/resources/views/begin.html | 19 +- .../web/nirc_ehr/buttons/SelectCaseButton.js | 5 + .../nirc_ehr/buttons/addClinicalObsButton.js | 88 ++++++- .../nirc_ehr/buttons/clinicalObsGridButton.js | 18 ++ .../nirc_ehr/model/sources/BulkClinical.js | 44 ++-- .../nirc_ehr/model/sources/ClinicalCase.js | 89 ++++++- .../model/sources/ClinicalDefaults.js | 41 +++ .../nirc_ehr/model/sources/ClinicalRounds.js | 126 ++++++++++ .../web/nirc_ehr/model/sources/NIRCDefault.js | 39 +++ .../resources/web/nirc_ehr/nircReports.js | 24 +- .../org/labkey/nirc_ehr/NIRC_EHRManager.java | 8 + .../org/labkey/nirc_ehr/NIRC_EHRModule.java | 1 + .../form/NIRCBulkClinicalFormType.java | 6 +- .../dataentry/form/NIRCCasesFormType.java | 4 +- .../NIRCClinicalObservationsFormType.java | 13 +- .../form/NIRCClinicalRoundsFormType.java | 113 +++++++++ .../NIRCClinicalObservationsFormSection.java | 41 ++- .../NIRCObservationOrdersFormSection.java | 54 ++++ .../nirc_ehr/query/NIRC_EHRTriggerHelper.java | 185 +++++++++----- .../nirc_ehr/table/NIRC_EHRCustomizer.java | 236 +++++++++++++++++- .../test/sampledata/nircEHRStudyPolicy.xml | 6 + 34 files changed, 1346 insertions(+), 183 deletions(-) create mode 100644 nirc_ehr/resources/queries/study/observationSchedule.query.xml create mode 100644 nirc_ehr/resources/queries/study/observationSchedule.sql create mode 100644 nirc_ehr/resources/queries/study/observationSchedule/.qview.xml create mode 100644 nirc_ehr/resources/queries/study/observation_order.js create mode 100644 nirc_ehr/resources/queries/study/observation_order.query.xml create mode 100644 nirc_ehr/resources/queries/study/observation_order/.qview.xml create mode 100644 nirc_ehr/resources/queries/study/observation_order/Active Orders.qview.xml create mode 100644 nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalRounds.js create mode 100644 nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCClinicalRoundsFormType.java create mode 100644 nirc_ehr/src/org/labkey/nirc_ehr/dataentry/section/NIRCObservationOrdersFormSection.java diff --git a/nirc_ehr/resources/queries/study/cases.js b/nirc_ehr/resources/queries/study/cases.js index fd88091e..daa558f1 100644 --- a/nirc_ehr/resources/queries/study/cases.js +++ b/nirc_ehr/resources/queries/study/cases.js @@ -4,6 +4,7 @@ * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 */ +const console = require("console"); require("ehr/triggers").initScript(this); var triggerHelper = new org.labkey.nirc_ehr.query.NIRC_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); @@ -15,3 +16,28 @@ EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Even } } }); + +EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.COMPLETE, 'study', 'cases', function(event, errors, helper){ + if (!helper.isETL()) { + var rows = helper.getRows(); + if (helper.getEvent() == 'insert' && rows.length && !helper.isValidateOnly()) { + for (var i = 0; i < rows.length; i++) { + var row = rows[i].row; + var qc; + if (row.QCStateLabel) { + qc = EHR.Server.Security.getQCStateByLabel(row.QCStateLabel); + } + else if (row.QCState) { + qc = EHR.Server.Security.getQCStateByRowId(row.QCState); + } + + if (!qc) { + console.error('Unable to find QCState: ' + row.QCState + '/' + row.QCStateLabel); + } + else if (qc.Label != 'COMPLETED' && row.caseid && row.Id && qc) { + triggerHelper.ensureDailyClinicalObservationOrders(row.Id, row.caseid, row.performedby, qc.RowId); + } + } + } + } +}); diff --git a/nirc_ehr/resources/queries/study/clinical_observations.js b/nirc_ehr/resources/queries/study/clinical_observations.js index bb02762d..ad65d4d8 100644 --- a/nirc_ehr/resources/queries/study/clinical_observations.js +++ b/nirc_ehr/resources/queries/study/clinical_observations.js @@ -4,41 +4,12 @@ * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 */ +const console = require("console"); require("ehr/triggers").initScript(this); var animalIdCasesMap = {}; var triggerHelper = new org.labkey.nirc_ehr.query.NIRC_EHRTriggerHelper(LABKEY.Security.currentUser.id, LABKEY.Security.currentContainer.id); -function onInit(event, helper){ - - LABKEY.Query.selectRows({ - schemaName: 'study', - queryName: 'cases', - columns: ['Id', 'caseid', 'taskid', 'enddate'], - scope: this, - sort: 'Id', - success: function (results) { - if (!results || !results.rows || results.rows.length < 1) - return; - - for(var i=0; i < results.rows.length; i++) { - - // get all open cases associated with an animal - if (null === results.rows[i]["enddate"]) { - var animal = results.rows[i]["Id"]; - if (!animalIdCasesMap[animal]) { - animalIdCasesMap[animal] = []; - } - animalIdCasesMap[animal].push(results.rows[i]); - } - } - // console.log("animalIdCasesMap: " + JSON.stringify(animalIdCasesMap)); - }, - failure: function (error) { - console.log("error getting death data in death trigger onInit()\n" + error); - } - }); -} function onUpsert(helper, scriptErrors, row, oldRow) { @@ -53,14 +24,21 @@ function onUpsert(helper, scriptErrors, row, oldRow) { EHR.Server.Utils.addError(scriptErrors, 'remark', "You selected 'No' for 'Verified Id?', please enter Remark", "WARN"); } - // if (!helper.isValidateOnly()) { - // if (row.Id) { - // if (animalIdCasesMap[row.Id] && animalIdCasesMap[row.Id].length > 0) { - // - //TODO: - // triggerHelper.addClinicalObsForCases(row, oldRow, animalIdCasesMap[row.Id]); //Add clinical obs for all open cases associated with an animal - // } - // } - // } + if (!helper.isValidateOnly()) { + var qc; + if (row.QCStateLabel) { + qc = EHR.Server.Security.getQCStateByLabel(row.QCStateLabel); + } + else if (row.QCState) { + qc = EHR.Server.Security.getQCStateByRowId(row.QCState); + } + + if (!qc) { + console.error('Unable to find QCState: ' + row.QCState + '/' + row.QCStateLabel); + } + else { + triggerHelper.propagateClinicalObs(row, qc.RowId); //Add clinical obs for all open cases associated with an animal + } + } } } \ No newline at end of file diff --git a/nirc_ehr/resources/queries/study/clinical_observations.query.xml b/nirc_ehr/resources/queries/study/clinical_observations.query.xml index 3088238c..937eea31 100644 --- a/nirc_ehr/resources/queries/study/clinical_observations.query.xml +++ b/nirc_ehr/resources/queries/study/clinical_observations.query.xml @@ -39,6 +39,10 @@ Scheduled Date + + Type + true +
diff --git a/nirc_ehr/resources/queries/study/observationSchedule.query.xml b/nirc_ehr/resources/queries/study/observationSchedule.query.xml new file mode 100644 index 00000000..1b13123f --- /dev/null +++ b/nirc_ehr/resources/queries/study/observationSchedule.query.xml @@ -0,0 +1,22 @@ + + + + + + Observation Schedule + + + + Scheduled Date/Time + + + Observations + + + + + +
+
+
+
\ No newline at end of file diff --git a/nirc_ehr/resources/queries/study/observationSchedule.sql b/nirc_ehr/resources/queries/study/observationSchedule.sql new file mode 100644 index 00000000..75c04700 --- /dev/null +++ b/nirc_ehr/resources/queries/study/observationSchedule.sql @@ -0,0 +1,111 @@ +SELECT + g.id, + g.scheduledDate, + COUNT(g.caseid) cases, + COUNT(g.taskid) orders, + g.observations, + GROUP_CONCAT(g.status, ';') as status, + MAX(g.taskid) as taskid, + MAX(g.type) as type, + MAX(g.caseid) as caseid +FROM +( + SELECT + sr.id, + sr.taskid, + sr.scheduledDate, + sr.caseid, + sr.type, + sr.observations, + sr.obsCount, + sr.statusCount, + sr.status + FROM + ( + SELECT + sch.id, + sch.taskid, + sch.date as scheduledDate, + sch.caseid, + sch.type, + GROUP_CONCAT(sch.category, ';') as observations, + GROUP_CONCAT(obsStatus, ';') as status, + COUNT(sch.category) as obsCount, + COUNT(sch.obsStatus) as statusCount + FROM + ( + SELECT + d.id, + s.*, + s.category, + co.qcstate.label as obsStatus + FROM study.demographics d JOIN + (SELECT + s1.*, + timestampadd('SQL_TSI_MINUTE', ((s1.hours * 60) + s1.minutes), s1.origDate) as date, + ((s1.hours * 60) + s1.minutes) as timeOffset + + FROM ( + + SELECT + t1.lsid, + t1.dataset, + t1.id as animalid, + + coalesce(ft.hourofday, ((hour(t1.date) * 100) + minute(t1.date))) as time, + (coalesce(ft.hourofday, (hour(t1.date) * 100)) / 100) as hours, + + CASE WHEN ft.hourofday IS NOT NULL + THEN (((ft.hourofday / 100.0) - floor(ft.hourofday / 100)) * 100) + ELSE minute(t1.date) + END as minutes, + + dr.date as origDate, + + t1.frequency.meaning as frequency, + t1.date as startDate, + timestampdiff('SQL_TSI_DAY', cast(t1.dateOnly as timestamp), dr.dateOnly) + 1 as daysElapsed, + t1.enddate, + t1.category, + t1.area, + t1.performedby, + t1.remark, + t1.caseid, + t1.taskid, + t1.type, + + t1.qcstate + + FROM nirc_ehr.dateRange dr + + JOIN + + -- order by category to replace string with Daily Obs + (SELECT * FROM + study.observation_order + ORDER BY category) t1 + ON (dr.dateOnly >= t1.dateOnly and dr.dateOnly <= t1.enddateCoalesced AND + --technically the first day of the treatment is day 1, not day 0 + ((mod(CAST(timestampdiff('SQL_TSI_DAY', CAST(t1.dateOnly as timestamp), dr.dateOnly) as integer), t1.frequency.intervalindays) = 0 And t1.frequency.intervalindays is not null And t1.frequency.dayofweek is null))) + + LEFT JOIN ehr_lookups.treatment_frequency_times ft ON ft.frequency = t1.frequency.meaning + + WHERE t1.date is not null AND t1.qcstate.publicdata = true + + ) s1 + + ) s ON (s.animalid = d.id) + LEFT JOIN study.clinical_observations co ON s.category = co.category AND co.scheduledDate IS NOT NULL AND s.date = co.scheduledDate AND co.id = s.animalid AND co.caseid = s.caseid + ) sch + GROUP BY + sch.id, + sch.taskid, + sch.date, + sch.caseid, + sch.type + ) sr +) g +GROUP BY + g.id, + g.scheduledDate, + g.observations diff --git a/nirc_ehr/resources/queries/study/observationSchedule/.qview.xml b/nirc_ehr/resources/queries/study/observationSchedule/.qview.xml new file mode 100644 index 00000000..4811d807 --- /dev/null +++ b/nirc_ehr/resources/queries/study/observationSchedule/.qview.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nirc_ehr/resources/queries/study/observation_order.js b/nirc_ehr/resources/queries/study/observation_order.js new file mode 100644 index 00000000..72d57b2b --- /dev/null +++ b/nirc_ehr/resources/queries/study/observation_order.js @@ -0,0 +1 @@ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nirc_ehr/resources/queries/study/observation_order.query.xml b/nirc_ehr/resources/queries/study/observation_order.query.xml new file mode 100644 index 00000000..f2eb124e --- /dev/null +++ b/nirc_ehr/resources/queries/study/observation_order.query.xml @@ -0,0 +1,45 @@ + + + + + Observation Orders + + + + DateTime + + + false + DateTime + + + Category + + + Area + + ehr_lookups + observation_areas + value + + + + + Frequency + + ehr_lookups + treatment_frequency + rowid + + + + Ordered By + + + Type + + +
+
+
+
\ No newline at end of file diff --git a/nirc_ehr/resources/queries/study/observation_order/.qview.xml b/nirc_ehr/resources/queries/study/observation_order/.qview.xml new file mode 100644 index 00000000..511375dc --- /dev/null +++ b/nirc_ehr/resources/queries/study/observation_order/.qview.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nirc_ehr/resources/queries/study/observation_order/Active Orders.qview.xml b/nirc_ehr/resources/queries/study/observation_order/Active Orders.qview.xml new file mode 100644 index 00000000..aaff737b --- /dev/null +++ b/nirc_ehr/resources/queries/study/observation_order/Active Orders.qview.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml index 5dfbd840..6f69f6f8 100644 --- a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml +++ b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml @@ -26,6 +26,7 @@ + diff --git a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml index be1809e1..9abfc5bf 100644 --- a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml +++ b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml @@ -334,6 +334,9 @@ http://cpas.labkey.com/Study#VisitDate http://cpas.labkey.com/Study#VisitDate
+ + timestamp + Type varchar @@ -348,6 +351,9 @@ varchar urn:ehr.labkey.org/#CaseId + + varchar + @@ -1363,4 +1369,44 @@ Fostering
+ + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + varchar + + + varchar + + + varchar + urn:ehr.labkey.org/#CaseId + + + timestamp + urn:ehr.labkey.org/#EndDate + + + integer + + + integer + + + varchar + + + Observation Orders +
\ No newline at end of file diff --git a/nirc_ehr/resources/reports/additionalReports.tsv b/nirc_ehr/resources/reports/additionalReports.tsv index 06ea6a27..27867bdc 100644 --- a/nirc_ehr/resources/reports/additionalReports.tsv +++ b/nirc_ehr/resources/reports/additionalReports.tsv @@ -11,6 +11,9 @@ alias Colony Management query Aliases true study demographicsAliases false f activeClinTreatmentOrders Clinical query Active Medication Orders true study treatment_order Clinical Active Treatment Orders date false false qcstate/publicdata This report contains the treatment orders entered for each animal allTreatments Clinical query All Treatment Orders true study treatment_order false false qcstate/publicdata This report shows all treatment orders FileRepository General js File Repository true study FileRepository false false qcstate/publicdata File Repository for uploading and viewing animal related files +observationSchedule Daily Reports js Observation Schedule true study observationSchedule date false false qcstate/publicdata This report contains a list of today's treatments to be administered +activeObservationOrders Clinical query Active Observation Orders true study observation_order Active Orders date false false qcstate/publicdata This report contains a list of today's treatments to be administered +observationOrders Clinical query Observation Orders true study observation_order date false false qcstate/publicdata This report contains a list of today's treatments to be administered behaviorCases behaviorRemarks bloodSchedule diff --git a/nirc_ehr/resources/views/begin.html b/nirc_ehr/resources/views/begin.html index d2746791..9de972cd 100644 --- a/nirc_ehr/resources/views/begin.html +++ b/nirc_ehr/resources/views/begin.html @@ -147,7 +147,7 @@ renderTo: 'ehrMenu2_' + webpart.wrapperDivId, sections: [ { - header: 'Daily Reports', + header: 'Cases', itemDefaults: { linkCls: 'none', style: 'font-weight: bold;' @@ -157,16 +157,25 @@ ] }, { - header: 'Medications/Observations', + header: 'Medications and Treatments', itemDefaults: { linkCls: 'none', style: 'font-weight: bold;' }, items: [ - {name: 'Today\'s Medication Schedule', url: '<%=contextPath%>' + ctx['EHRStudyContainer'] + '/ehr-animalHistory.view#inputType:none&showReport:1&activeReport:clinMedicationSchedule'}, - // {name: 'Today\'s Observation Schedule', url: '<%=contextPath%>' + ctx['EHRStudyContainer'] + '/ehr-animalHistory.view#inputType:none&showReport:1&activeReport:observationSchedule'}, + {name: 'Today\'s Medication/Treatment Schedule', url: '<%=contextPath%>' + ctx['EHRStudyContainer'] + '/ehr-animalHistory.view#inputType:none&showReport:1&activeReport:clinMedicationSchedule'}, {name: 'Active Clinical Medication Orders', url: '<%=contextPath%>' + ctx['EHRStudyContainer'] + '/ehr-animalHistory.view#inputType:none&showReport:1&activeReport:activeClinTreatmentOrders'}, - // {name: 'Active Observation Orders', url: '<%=contextPath%>' + ctx['EHRStudyContainer'] + '/ehr-animalHistory.view#inputType:none&showReport:1&activeReport:activeObservationOrders'}, + ] + }, + { + header: 'Observations', + itemDefaults: { + linkCls: 'none', + style: 'font-weight: bold;' + }, + items: [ + {name: 'Today\'s Observation Schedule', url: '<%=contextPath%>' + ctx['EHRStudyContainer'] + '/ehr-animalHistory.view#inputType:none&showReport:1&activeReport:observationSchedule'}, + {name: 'Active Observation Orders', url: '<%=contextPath%>' + ctx['EHRStudyContainer'] + '/ehr-animalHistory.view#inputType:none&showReport:1&activeReport:activeObservationOrders'}, ] } ] diff --git a/nirc_ehr/resources/web/nirc_ehr/buttons/SelectCaseButton.js b/nirc_ehr/resources/web/nirc_ehr/buttons/SelectCaseButton.js index eb09f8e4..af751156 100644 --- a/nirc_ehr/resources/web/nirc_ehr/buttons/SelectCaseButton.js +++ b/nirc_ehr/resources/web/nirc_ehr/buttons/SelectCaseButton.js @@ -15,6 +15,11 @@ Ext4.define('NIRC_EHR.form.field.SelectCaseButton', { const rec = store.getAt(0); EHR.DemographicsCache.reportCaseSelected(rec); panel.fireEvent('animalchange', rec.data.Id); + + let editCases = this.up('#upperPanel')?.query('nirc_ehr-editCases')?.[0]; + editCases.fieldEnableChange(true); + if (hideEdit) + editCases.editBtn.hide(); }); }, diff --git a/nirc_ehr/resources/web/nirc_ehr/buttons/addClinicalObsButton.js b/nirc_ehr/resources/web/nirc_ehr/buttons/addClinicalObsButton.js index d2272516..f371b45c 100644 --- a/nirc_ehr/resources/web/nirc_ehr/buttons/addClinicalObsButton.js +++ b/nirc_ehr/resources/web/nirc_ehr/buttons/addClinicalObsButton.js @@ -9,25 +9,89 @@ EHR.DataEntryUtils.registerGridButton('NIRC_DAILY_CLINICAL_OBS', function(config queryName: 'observation_types', success: function (results) { var grid = btn.up('gridpanel'); - if (grid?.store?.data?.getCount() === 0) { - if (results?.rows?.length > 0) { - for (var i = 0; i < results.rows.length; i++) { - var row = results.rows[i]; - if (row.value === 'Verified Id?' || row.value === 'Stool' || row.value === 'Activity' || - row.value === 'Appetite' || row.value === 'Hydration' || row.value === 'BCS') { + if (results?.rows?.length > 0) { + for (var i = 0; i < results.rows.length; i++) { + var row = results.rows[i]; + if (row.value === 'Verified Id?' || row.value === 'Stool' || row.value === 'Activity' || + row.value === 'Appetite' || row.value === 'Hydration' || row.value === 'BCS') { - var newRecord = grid.store.createModel({}); - newRecord.set({ - category: row.value, - }); - grid.store.add(newRecord); - } + var newRecord = grid.store.createModel({}); + newRecord.set({ + category: row.value, + }); + grid.store.add(newRecord); } } } + else { + Ext4.Msg.alert('Unable to load observation types. Please contact the system administrator.'); + } + }, + failure: function (error) { + Ext4.Msg.alert('Unable to load observation types. Please contact the system administrator.'); + console.log('Error loading observation types: ' + error); }, scope: this }); } }, config); +}); + +EHR.DataEntryUtils.registerGridButton('NIRC_DAILY_CLINICAL_OBS_ORDERS', function(config){ + return Ext4.Object.merge({ + text: 'Daily Observations', + tooltip: 'Click to delete selected rows', + handler: function(btn) { + LABKEY.Query.selectRows({ + schemaName: 'ehr_lookups', + queryName: 'treatment_frequency', + columns: 'rowid', + filterArray: [LABKEY.Filter.create('meaning', 'SID', LABKEY.Filter.Types.EQUAL)], + scope: this, + success: function (results) { + if (results?.rows?.length > 0) { + const sidRowId = results.rows[0].rowid; + LABKEY.Query.selectRows({ + schemaName: 'ehr', + queryName: 'observation_types', + success: function (results) { + var grid = btn.up('gridpanel'); + if (results?.rows?.length > 0) { + for (var i = 0; i < results.rows.length; i++) { + var row = results.rows[i]; + if (row.value === 'Verified Id?' || row.value === 'Stool' || row.value === 'Activity' || + row.value === 'Appetite' || row.value === 'Hydration' || row.value === 'BCS') { + + var newRecord = grid.store.createModel({}); + newRecord.set({ + category: row.value, + frequency: sidRowId + }); + grid.store.add(newRecord); + } + } + } + else { + Ext4.Msg.alert('Unable to load observation types. Please contact the system administrator.'); + } + }, + failure: function (error) { + Ext4.Msg.alert('Unable to load observation types. Please contact the system administrator.'); + console.log('Error loading observation types: ' + error); + }, + scope: this + }); + } + else { + Ext4.Msg.alert('Unable to load treatment frequencies. Please contact the system administrator.'); + } + }, + failure: function (error) { + Ext4.Msg.alert('Unable to load treatment frequencies. Please contact the system administrator.'); + console.log('Error loading treatment frequencies: ' + error); + } + }); + + } + }, config); }); \ No newline at end of file diff --git a/nirc_ehr/resources/web/nirc_ehr/buttons/clinicalObsGridButton.js b/nirc_ehr/resources/web/nirc_ehr/buttons/clinicalObsGridButton.js index f9831c87..f9fb277d 100644 --- a/nirc_ehr/resources/web/nirc_ehr/buttons/clinicalObsGridButton.js +++ b/nirc_ehr/resources/web/nirc_ehr/buttons/clinicalObsGridButton.js @@ -5,6 +5,11 @@ EHR.DataEntryUtils.registerGridButton('NIRC_AUTO_POPULATE_DAILY_OBS', function(c hidden: true, listeners: { render: function(btn){ + const id = LABKEY.ActionURL.getParameter('id'); + const caseid = LABKEY.ActionURL.getParameter('caseid'); + const scheduledDate = LABKEY.ActionURL.getParameter('scheduledDate'); + const scheduled = id && caseid && scheduledDate; + LABKEY.Query.selectRows({ schemaName: 'ehr', queryName: 'observation_types', @@ -21,9 +26,22 @@ EHR.DataEntryUtils.registerGridButton('NIRC_AUTO_POPULATE_DAILY_OBS', function(c newRecord.set({ category: row.value, }); + + if (scheduled) { + newRecord.set('Id', id); + newRecord.set('caseid', caseid); + newRecord.set('scheduledDate', scheduledDate); + } grid.store.add(newRecord); } } + + if (scheduled) { + this.addEvents('animalchange'); + this.enableBubble('animalchange'); + this.fireEvent('animalchange', id); + grid.fireEvent('panelDataChange'); + } } } }, diff --git a/nirc_ehr/resources/web/nirc_ehr/model/sources/BulkClinical.js b/nirc_ehr/resources/web/nirc_ehr/model/sources/BulkClinical.js index 057b53b2..d9764543 100644 --- a/nirc_ehr/resources/web/nirc_ehr/model/sources/BulkClinical.js +++ b/nirc_ehr/resources/web/nirc_ehr/model/sources/BulkClinical.js @@ -1,14 +1,4 @@ EHR.model.DataModelManager.registerMetadata('BulkClinical', { - allQueries: { - category: { - defaultValue: 'Clinical', - hidden: true - }, - project: { - hidden: true, - allowBlank: true - }, - }, byQuery: { 'study.clinremarks': { p: { @@ -37,23 +27,27 @@ EHR.model.DataModelManager.registerMetadata('BulkClinical', { remark: { allowBlank: true }, - }, - 'study.clinical_observations': { category: { - hidden: false - }, - remark: { - allowBlank: true - }, - }, - 'study.blood': { - units: { - hidden: true + getInitialValue: function (v, rec) { + return 'Clinical' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } }, - }, - 'study.vitals': { - units: { - hidden: true + performedby: { + hidden: false, + defaultValue: LABKEY.Security.currentUser.id.toString(), + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'core', + sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', + autoLoad: true + } + } }, } } diff --git a/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalCase.js b/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalCase.js index a41dd25a..96834d08 100644 --- a/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalCase.js +++ b/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalCase.js @@ -67,7 +67,94 @@ EHR.model.DataModelManager.registerMetadata('ClinicalCase', { } } }, + }, + openRemark: { + height: 120 + }, + plan: { + height: 120 + }, + closeRemark: { + height: 120 + }, + qcstate: { + hidden: true + }, + openDiagnosis: { + hidden: true + }, + closeDiagnosis: { + hidden: true + }, + attachmentFile: { + hidden: true + }, + caseCategory: { + hidden: true + }, + performedby: { + hidden: false, + defaultValue: LABKEY.Security.currentUser.id.toString(), + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'core', + sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', + autoLoad: true + } + } + }, + formCasesLink: { + xtype: 'nirc_ehr-editCases' } - } + }, + 'study.clinremarks': { + hx: { + formEditorConfig: { + xtype: 'ehr-hxtextarea' + }, + }, + p: { + height: 120 + }, + remark: { + label: 'Remark', + height: 120 + }, + vetreview: { + height: 120 + }, + category: { + getInitialValue: function (v, rec) { + return 'Clinical' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + performedby: { + hidden: false, + defaultValue: LABKEY.Security.currentUser.id.toString(), + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'core', + sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', + autoLoad: true + } + } + }, + enddate: { + hidden: true + }, + dateFinalized: { + hidden: true + }, + qcstate: { + hidden: true + }, + }, } }); \ No newline at end of file diff --git a/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalDefaults.js b/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalDefaults.js index bca28ddd..4d3e794f 100644 --- a/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalDefaults.js +++ b/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalDefaults.js @@ -52,6 +52,31 @@ EHR.model.DataModelManager.registerMetadata('ClinicalDefaults', { reason: { defaultValue: 'Clinical', hidden: true + }, + performedby: { + hidden: false, + defaultValue: LABKEY.Security.currentUser.id.toString(), + editorConfig: { + store: { + type: 'labkey-store', + schemaName: 'core', + + // 'performedby' is a text field in the dataset and its lookup to the userid is an int field - this mismatch causes it to disappear + // from the display when a value is selected from the dropdown even though the 'userid' value gets saved as a text (this behavior was only seen + // in the form panel but not in the grid panel). + // casting it as a varchar when loading the store fixes this issue. + sql: 'SELECT CAST (UserId AS VARCHAR) AS UserId,DisplayName,FirstName,LastName FROM core.users', + autoLoad: true + } + } + }, + category: { + defaultValue: 'Clinical', + hidden: true, + allowBlank: false + }, + units: { + hidden: true } }, 'study.cases': { @@ -122,10 +147,26 @@ EHR.model.DataModelManager.registerMetadata('ClinicalDefaults', { hidden: true }, }, + + 'study.clinical_observations': { + type: { + hidden: true, + defaultValue: 'Clinical' + } + }, 'study.vitals': { category: { defaultValue: 'Clinical', hidden: true + }, + units: { + hidden: true + } + }, + 'study.observation_order': { + type: { + hidden: true, + defaultValue: 'Clinical' } } } diff --git a/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalRounds.js b/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalRounds.js new file mode 100644 index 00000000..a4434c5d --- /dev/null +++ b/nirc_ehr/resources/web/nirc_ehr/model/sources/ClinicalRounds.js @@ -0,0 +1,126 @@ +EHR.model.DataModelManager.registerMetadata('ClinicalRounds', { + allQueries: { + Id: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + date: { + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + caseid: { + inheritFromParent: true, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + } + }, + byQuery: { + 'study.cases': { + Id: { + xtype: 'nirc_ehr-animalIdCases', + inheritFromParent: false, + editable: true, + hidden: false, + columnConfig: { + editable: true + } + }, + date: { + id: 'open_date', + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + }, + getInitialValue: function(v, rec){ + return null; + } + }, + enddate: { + id: 'close_date', + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + category: { + getInitialValue: function (v, rec){ + return 'Clinical' + }, + editable: false, + hidden: true, + columnConfig: { + editable: false + } + }, + problemCategory: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + problemSubcategory: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + plan: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + openRemark: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + closeRemark: { + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + performedby: { + hidden: false, + editorConfig: { + editable: false, + disabled: true, + fieldCls: 'form-panel-input-disabled', + labelClsExtra: 'form-panel-input-disabled' + } + }, + formCasesLink: { + xtype: 'nirc_ehr-editCases', + editorConfig: { + readonly: true + } + }, + } + } +}); \ No newline at end of file diff --git a/nirc_ehr/resources/web/nirc_ehr/model/sources/NIRCDefault.js b/nirc_ehr/resources/web/nirc_ehr/model/sources/NIRCDefault.js index 1e31627b..7bed8f3e 100644 --- a/nirc_ehr/resources/web/nirc_ehr/model/sources/NIRCDefault.js +++ b/nirc_ehr/resources/web/nirc_ehr/model/sources/NIRCDefault.js @@ -127,5 +127,44 @@ EHR.model.DataModelManager.registerMetadata('Default', { nullable: true }, }, + 'study.observation_order': { + category: { + allowBlank: false, + editorConfig: { + plugins: [Ext4.create('LDK.plugin.UserEditableCombo', { + allowChooseOther: false + })] + }, + lookup: { + columns: 'value,description' + }, + columnConfig: { + width: 200 + } + }, + area: { + defaultValue: 'N/A', + columnConfig: { + width: 200 + } + }, + observation: { + columnConfig: { + width: 200 + } + }, + remark: { + columnConfig: { + width: 300 + } + }, + frequency: { + columnConfig: { + width: 180 + }, + nullable: false, + allowBlank: true + } + } } }); \ No newline at end of file diff --git a/nirc_ehr/resources/web/nirc_ehr/nircReports.js b/nirc_ehr/resources/web/nirc_ehr/nircReports.js index 51dd22d5..b8ab1b6c 100644 --- a/nirc_ehr/resources/web/nirc_ehr/nircReports.js +++ b/nirc_ehr/resources/web/nirc_ehr/nircReports.js @@ -196,4 +196,26 @@ EHR.reports.clinicalHistory = function(panel, tab, showActionsBtn, includeAll){ tab.add(toAdd); } } -}; \ No newline at end of file +}; + +EHR.reports.observationSchedule = function(panel, tab, viewName){ + var filterArray = panel.getFilterArray(tab); + var title = panel.getTitleSuffix(); + + var date = Ext4.Date.format(new Date(), LABKEY.extDefaultDateFormat); + tab.add({ + xtype: 'ldk-querypanel', + style: 'margin-bottom:20px;', + queryConfig: panel.getQWPConfig({ + schemaName: 'study', + queryName: 'observationSchedule', + title: 'Observation Schedule ' + title, + filters: filterArray.nonRemovable, + removeableFilters: filterArray.removable, + parameters: { + StartDate: date, + NumDays: 1 + } + }) + }); +} \ No newline at end of file diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRManager.java b/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRManager.java index 55ef3584..663cc589 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRManager.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRManager.java @@ -1,7 +1,15 @@ package org.labkey.nirc_ehr; +import org.labkey.api.query.Queryable; + +import java.util.List; + public class NIRC_EHRManager { + @Queryable + public static final String DAILY_CLINICAL_OBS_TITLE = "Daily Clinical Observations"; + public static final List DAILY_CLINICAL_OBS = List.of("Activity", "Appetite", "BCS", "Hydration", "Stool", "Verified Id?"); + public static final String DAILY_CLINICAL_OBS_LIST = String.join(";",NIRC_EHRManager.DAILY_CLINICAL_OBS); private static NIRCOrchardFileGenerator _orchardFileGenerator = new NIRCOrchardFileGenerator(); public static NIRCOrchardFileGenerator getOrchardFileGenerator() { diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java b/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java index 8d6df46e..8a0396c3 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java @@ -195,6 +195,7 @@ private void registerDataEntry() EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NIRCFloorFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NIRCCageFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NIRCClinicalObservationsFormType.class, this)); + EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NIRCClinicalRoundsFormType.class, this)); } @Override diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCBulkClinicalFormType.java b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCBulkClinicalFormType.java index ad082aef..97cfa0a6 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCBulkClinicalFormType.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCBulkClinicalFormType.java @@ -10,6 +10,7 @@ import org.labkey.nirc_ehr.dataentry.section.NIRCBloodDrawFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCClinicalObservationsFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCClinicalRemarksFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCObservationOrdersFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCProcedureFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCTaskFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCTreatmentGivenFormSection; @@ -34,7 +35,8 @@ public NIRCBulkClinicalFormType(DataEntryFormContext ctx, Module owner) ctx.getContainer().hasPermission(ctx.getUser(), EHRVeterinarianPermission.class), ctx.getContainer().hasPermission(ctx.getUser(), AdminPermission.class)), new NIRCProcedureFormSection(), - new NIRCClinicalObservationsFormSection(true, false, true), + new NIRCClinicalObservationsFormSection(false, null), + new NIRCObservationOrdersFormSection("NIRC_DAILY_CLINICAL_OBS_ORDERS", false, null), new NIRCTreatmentGivenFormSection(), new NIRCTreatmentOrderFormSection(), new NIRCWeightFormSection(true, true), @@ -42,6 +44,7 @@ public NIRCBulkClinicalFormType(DataEntryFormContext ctx, Module owner) new NIRCBloodDrawFormSection(true, true, true) )); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/ClinicalDefaults.js")); addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/BulkClinical.js")); addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/TreatmentSchedule.js")); addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/field/DrugVolumeField.js")); @@ -49,6 +52,7 @@ public NIRCBulkClinicalFormType(DataEntryFormContext ctx, Module owner) for (FormSection s : getFormSections()) { + s.addConfigSource("ClinicalDefaults"); s.addConfigSource("BulkClinical"); s.addConfigSource("TreatmentSchedule"); }; diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCCasesFormType.java b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCCasesFormType.java index a66d891a..75140c9a 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCCasesFormType.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCCasesFormType.java @@ -17,6 +17,7 @@ import org.labkey.nirc_ehr.dataentry.section.NIRCClinicalObservationsFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCClinicalRemarksFormPanelSection; import org.labkey.nirc_ehr.dataentry.section.NIRCHousingFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCObservationOrdersFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCProcedureFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCTaskFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCTreatmentGivenFormSection; @@ -49,7 +50,8 @@ public NIRCCasesFormType(DataEntryFormContext ctx, Module owner) ctx.getContainer().hasPermission(ctx.getUser(), EHRVeterinarianPermission.class), ctx.getContainer().hasPermission(ctx.getUser(), AdminPermission.class)), new NIRCProcedureFormSection(true, "cases"), - new NIRCClinicalObservationsFormSection(true, false, true), + new NIRCClinicalObservationsFormSection(true, "cases"), + new NIRCObservationOrdersFormSection(null, true, "cases"), new NIRCTreatmentGivenFormSection(true, "cases"), new NIRCTreatmentOrderFormSection(true, "cases"), new NIRCWeightFormSection(true, false, true, "cases"), diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCClinicalObservationsFormType.java b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCClinicalObservationsFormType.java index 3c712d47..c05e625e 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCClinicalObservationsFormType.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCClinicalObservationsFormType.java @@ -8,9 +8,7 @@ import org.labkey.nirc_ehr.dataentry.section.NIRCClinicalObservationsFormSection; import org.labkey.nirc_ehr.dataentry.section.NIRCTaskFormSection; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; public class NIRCClinicalObservationsFormType extends NIRCBaseTaskFormType { @@ -21,7 +19,7 @@ public NIRCClinicalObservationsFormType(DataEntryFormContext ctx, Module owner) super(ctx, owner, NAME, NAME, "Clinical", Arrays.asList( new NIRCTaskFormSection(), new NIRCAnimalDetailsFormSection(), - new NIRCClinicalObservationsFormSection(true, true, false) + new NIRCClinicalObservationsFormSection(true, false) )); addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/ClinicalDefaults.js")); @@ -31,13 +29,4 @@ public NIRCClinicalObservationsFormType(DataEntryFormContext ctx, Module owner) s.addConfigSource("ClinicalDefaults"); } } - - @Override - protected List getButtonConfigs() - { - List defaultButtons = new ArrayList(); - defaultButtons.add("SAVEDRAFT"); - defaultButtons.add("SUBMIT"); //submit final - return defaultButtons; - } } \ No newline at end of file diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCClinicalRoundsFormType.java b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCClinicalRoundsFormType.java new file mode 100644 index 00000000..0ac6d2ce --- /dev/null +++ b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCClinicalRoundsFormType.java @@ -0,0 +1,113 @@ +package org.labkey.nirc_ehr.dataentry.form; + +import org.labkey.api.ehr.dataentry.AbstractFormSection; +import org.labkey.api.ehr.dataentry.DataEntryFormContext; +import org.labkey.api.ehr.dataentry.FormSection; +import org.labkey.api.ehr.dataentry.SimpleFormSection; +import org.labkey.api.ehr.security.EHRClinicalEntryPermission; +import org.labkey.api.ehr.security.EHRVeterinarianPermission; +import org.labkey.api.module.Module; +import org.labkey.api.security.permissions.AdminPermission; +import org.labkey.api.view.template.ClientDependency; +import org.labkey.nirc_ehr.dataentry.section.NIRCAnimalDetailsFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCBloodDrawFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCCaseTemplateFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCCasesFormPanelSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCClinicalObservationsFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCHousingFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCObservationOrdersFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCProcedureFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCTaskFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCTreatmentGivenFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCTreatmentOrderFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCVitalsFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCWeightFormSection; +import org.labkey.nirc_ehr.security.NIRCEHRVetTechPermission; + +import java.util.Arrays; +import java.util.List; + +public class NIRCClinicalRoundsFormType extends NIRCBaseTaskFormType +{ + public static final String NAME = "Clinical Rounds"; + public static final String LABEL = "Clinical Rounds"; + + public NIRCClinicalRoundsFormType(DataEntryFormContext ctx, Module owner) + { + super(ctx, owner, NAME, LABEL, "Clinical", Arrays.asList( + new NIRCTaskFormSection(), + new NIRCAnimalDetailsFormSection(), + new NIRCCaseTemplateFormSection("Case Template", "Case Template", "nirc_ehr-casetemplatepanel", Arrays.asList(ClientDependency.supplierFromPath("nirc_ehr/panel/CaseTemplatePanel.js"))), + new NIRCCasesFormPanelSection("Clinical Case", + ctx.getContainer().hasPermission(ctx.getUser(), NIRCEHRVetTechPermission.class), + ctx.getContainer().hasPermission(ctx.getUser(), EHRVeterinarianPermission.class), + ctx.getContainer().hasPermission(ctx.getUser(), AdminPermission.class)), + new NIRCProcedureFormSection(true, "cases"), + new NIRCClinicalObservationsFormSection(true, "cases"), + new NIRCObservationOrdersFormSection(null, true, "cases"), + new NIRCTreatmentGivenFormSection(true, "cases"), + new NIRCTreatmentOrderFormSection(true, + "cases"), + new NIRCWeightFormSection(true, false, true, "cases"), + new NIRCVitalsFormSection(true, "cases"), + new NIRCHousingFormSection(true, true, true, "cases"), + new NIRCBloodDrawFormSection(true, true, true) + )); + + setTemplateMode(AbstractFormSection.TEMPLATE_MODE.NO_ID); + setDisplayReviewRequired(true); + + for (FormSection s : this.getFormSections()) + { + s.addConfigSource("ClinicalDefaults"); + s.addConfigSource("ClinicalCase"); + s.addConfigSource("ClinicalRounds"); + s.addConfigSource("TreatmentSchedule"); + + if (s instanceof SimpleFormSection && !s.getName().equals("tasks")) + s.setTemplateMode(AbstractFormSection.TEMPLATE_MODE.NO_ID); + + if (s instanceof AbstractFormSection) + { + ((AbstractFormSection)s).setAllowBulkAdd(false); + } + } + setStoreCollectionClass("NIRC_EHR.data.CaseStoreCollection"); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/data/CaseStoreCollection.js")); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/TreatmentSchedule.js")); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/field/DrugVolumeField.js")); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/window/DrugAmountWindow.js")); + + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/ClinicalDefaults.js")); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/ClinicalCase.js")); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/ClinicalRounds.js")); + addClientDependency(ClientDependency.supplierFromPath("ehr/panel/ExamDataEntryPanel.js")); + setJavascriptClass("EHR.panel.ExamDataEntryPanel"); + + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/panel/NIRCExamCasesDataEntryPanel.js")); + setJavascriptClass("NIRC_EHR.panel.ExamCasesDataEntryPanel"); + + // Needed for case and scheduled date/time when navigating from treatment or observation schedule + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/buttons/treatmentSubmit.js")); + } + + @Override + protected boolean canInsert() + { + if (!getCtx().getContainer().hasPermission(getCtx().getUser(), EHRClinicalEntryPermission.class)) + return false; + + return super.canInsert(); + } + + @Override + protected List getButtonConfigs() + { + List ret = super.getButtonConfigs(); + + ret.remove("SUBMIT"); + ret.add("NIRC_TREATMENT_SUBMIT"); + + return ret; + } +} diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/section/NIRCClinicalObservationsFormSection.java b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/section/NIRCClinicalObservationsFormSection.java index 32a8bdf6..d2af9e2e 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/section/NIRCClinicalObservationsFormSection.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/section/NIRCClinicalObservationsFormSection.java @@ -6,15 +6,13 @@ public class NIRCClinicalObservationsFormSection extends BaseFormSection { - public static final String LABEL = "Clinical Observations"; - private boolean _useDefaultButtons = true; + public static final String LABEL = "Observations"; private boolean _autoPopulateDailyObs = true; - public NIRCClinicalObservationsFormSection(boolean useDefaultBtns, boolean autoPopulateDailyObs, boolean initCollapsed) + public NIRCClinicalObservationsFormSection(boolean autoPopulateDailyObs, boolean initCollapsed) { super("study", "clinical_observations", LABEL, "ehr-clinicalobservationgridpanel", true, initCollapsed, true); - _useDefaultButtons = useDefaultBtns; _autoPopulateDailyObs = autoPopulateDailyObs; addClientDependency(ClientDependency.supplierFromPath("ehr/plugin/ClinicalObservationsCellEditing.js")); addClientDependency(ClientDependency.supplierFromPath("ehr/data/ClinicalObservationsClientStore.js")); @@ -23,6 +21,22 @@ public NIRCClinicalObservationsFormSection(boolean useDefaultBtns, boolean autoP addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/buttons/addClinicalObsButton.js")); setClientStoreClass("EHR.data.ClinicalObservationsClientStore"); } + + public NIRCClinicalObservationsFormSection(boolean isChild, String parentQueryName) + { + this(false, true); + + if (isChild && null != parentQueryName) + { + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/ParentChild.js")); + addConfigSource("ParentChild"); + + addClientDependency(ClientDependency.supplierFromPath("ehr/data/ChildClientStore.js")); + setClientStoreClass("EHR.data.ChildClientStore"); + addExtraProperty("parentQueryName", parentQueryName); + } + } + @Override public List getTbarButtons() { @@ -36,26 +50,7 @@ public List getTbarButtons() defaults.add("NIRC_DAILY_CLINICAL_OBS"); } - if (!_useDefaultButtons) - { - defaults.clear(); - defaults.add("ADDRECORD"); - defaults.add("DELETERECORD"); - } - return defaults; } - - @Override - public List getTbarMoreActionButtons() - { - List moreActionButtons = super.getTbarMoreActionButtons(); - if (!_useDefaultButtons) - { - moreActionButtons.clear(); - } - - return moreActionButtons; - } } diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/section/NIRCObservationOrdersFormSection.java b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/section/NIRCObservationOrdersFormSection.java new file mode 100644 index 00000000..8c6ac907 --- /dev/null +++ b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/section/NIRCObservationOrdersFormSection.java @@ -0,0 +1,54 @@ +package org.labkey.nirc_ehr.dataentry.section; + +import org.labkey.api.view.template.ClientDependency; + +import java.util.List; + +public class NIRCObservationOrdersFormSection extends BaseFormSection +{ + + public static final String LABEL = "Observation Orders"; + private String _dailyObsOption; + + public NIRCObservationOrdersFormSection(String dailyObsOption, boolean initCollapsed) + { + super("study", "observation_order", LABEL, "ehr-clinicalobservationgridpanel", true, initCollapsed, true); + + _dailyObsOption = dailyObsOption; + addClientDependency(ClientDependency.supplierFromPath("ehr/plugin/ClinicalObservationsCellEditing.js")); + addClientDependency(ClientDependency.supplierFromPath("ehr/data/ClinicalObservationsClientStore.js")); + addClientDependency(ClientDependency.supplierFromPath("ehr/grid/ClinicalObservationGridPanel.js")); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/buttons/clinicalObsGridButton.js")); + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/buttons/addClinicalObsButton.js")); + setClientStoreClass("EHR.data.ClinicalObservationsClientStore"); + } + + public NIRCObservationOrdersFormSection(String dailyObsOption, boolean isChild, String parentQueryName) + { + this(dailyObsOption, true); + + if (isChild && null != parentQueryName) + { + addClientDependency(ClientDependency.supplierFromPath("nirc_ehr/model/sources/ParentChild.js")); + addConfigSource("ParentChild"); + + addClientDependency(ClientDependency.supplierFromPath("ehr/data/ChildClientStore.js")); + setClientStoreClass("EHR.data.ChildClientStore"); + addExtraProperty("parentQueryName", parentQueryName); + } + } + + @Override + public List getTbarButtons() + { + List defaults = super.getTbarButtons(); + + if (_dailyObsOption != null) + { + defaults.add(_dailyObsOption); + } + + return defaults; + + } +} diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/query/NIRC_EHRTriggerHelper.java b/nirc_ehr/src/org/labkey/nirc_ehr/query/NIRC_EHRTriggerHelper.java index 2978f5d3..7c8a573b 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/query/NIRC_EHRTriggerHelper.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/query/NIRC_EHRTriggerHelper.java @@ -4,7 +4,6 @@ import org.apache.commons.lang3.mutable.MutableObject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Nullable; import org.labkey.api.collections.CaseInsensitiveHashMap; import org.labkey.api.data.ColumnInfo; import org.labkey.api.data.CompareType; @@ -19,7 +18,6 @@ import org.labkey.api.data.TableInfo; import org.labkey.api.data.TableSelector; import org.labkey.api.ehr.security.EHRVeterinarianPermission; -import org.labkey.api.exp.api.ExperimentService; import org.labkey.api.ldk.notification.NotificationService; import org.labkey.api.query.BatchValidationException; import org.labkey.api.query.DuplicateKeyException; @@ -576,62 +574,129 @@ public boolean canCloseCase(String category) return false; } - //Add clinical observations to all open cases for an animal so users don't need to add the same observation to each case individually - //TODO -// public void addClinicalObsForCases(Map clinicalObsRow, Map clinicalObsOldRow, List> openCasesPerAnimal, @Nullable String currentCaseId) throws SQLException, BatchValidationException, QueryUpdateServiceException, InvalidKeyException, DuplicateKeyException -// { -// if (null != currentCaseId) -// { -// boolean updateRecord = false; -// BatchValidationException errors = new BatchValidationException(); -// TableInfo ti = getTableInfo("study", "clinical_observations"); -// SimpleFilter filter = new SimpleFilter(FieldKey.fromString("Id"), clinicalObsRow.get("Id")); -// List> rows = new ArrayList<>(); -// -// // For each open case, add the clinical observation -// for (Map animalCase : openCasesPerAnimal) -// { -// String caseTaskId = (String) animalCase.get("taskid"); -// String caseId = (String) animalCase.get("caseid"); -// -// Map clinObsRowToInsert = new CaseInsensitiveHashMap<>(); -// clinObsRowToInsert.put("Id", clinicalObsRow.get("Id")); -// clinObsRowToInsert.put("date", clinicalObsRow.get("date")); -// clinObsRowToInsert.put("caseid", caseId); -// clinObsRowToInsert.put("qcstate", clinicalObsRow.get("qcstate")); -// clinObsRowToInsert.put("category", clinicalObsRow.get("category")); -// clinObsRowToInsert.put("observation", clinicalObsRow.get("observation")); -// clinObsRowToInsert.put("remark", clinicalObsRow.get("remark")); -// clinObsRowToInsert.put("taskId", caseTaskId); -// clinObsRowToInsert.put("performedby", clinicalObsRow.get("performedby")); -// -// filter.addCondition(FieldKey.fromString("taskid"), caseTaskId); -// filter.addCondition(FieldKey.fromString("objectid"), clinicalObsOldRow.get("objectid")); -// TableSelector ts = new TableSelector(ti, PageFlowUtil.set("lsid", "objectid"), filter, null); -// -// if (ts.exists()) -// { -// updateRecord = true; -// clinObsRowToInsert.put("objectid", ts.getMap().get("objectid")); -// } -// else -// { -// clinObsRowToInsert.put("objectid", new GUID().toString()); -// } -// -// rows.add(clinObsRowToInsert); -// -// if (updateRecord) -// { -// ti.getUpdateService().updateRows(_user, _container, rows, null, null, getExtraContext()); -// } -// else -// { -// ti.getUpdateService().insertRows(_user, _container, rows, errors, null, getExtraContext()); -// } -// if (errors.hasErrors()) -// throw errors; -// } -// } -// } + public void ensureDailyClinicalObservationOrders(String id, String caseid, String performedby, String qcstate) throws SQLException + { + TableInfo ti = getTableInfo("study", "observation_order"); + SimpleFilter filter = new SimpleFilter(FieldKey.fromParts("category","value"), "Activity"); + filter.addCondition(FieldKey.fromString("caseid"), caseid); + filter.addCondition(FieldKey.fromParts("frequency", "meaning"), "SID"); + TableSelector ts = new TableSelector(ti, PageFlowUtil.set("category","frequency"), filter, null); + + List missing = new ArrayList<>(NIRC_EHRManager.DAILY_CLINICAL_OBS); + ts.forEach(row -> { + if (row.getString("category") != null) + missing.remove(row.getString("category")); + }); + + if (!missing.isEmpty()) + { + TableInfo freqTi = getTableInfo("ehr_lookups", "treatment_frequency"); + filter = new SimpleFilter(FieldKey.fromString("meaning"), "SID"); + ts = new TableSelector(freqTi, PageFlowUtil.set("rowid"), filter, null); + try + { + int sidRowid = ts.getObject(Integer.class); + + List> rows = new ArrayList<>(); + for (String category : missing) + { + Map row = new CaseInsensitiveHashMap<>(); + row.put("category", category); + row.put("frequency", sidRowid); + row.put("caseid", caseid); + row.put("date", new Date()); + row.put("Id", id); + row.put("qcstate", qcstate); + row.put("area", "N/A"); + row.put("performedby", performedby); + rows.add(row); + } + + BatchValidationException errors = new BatchValidationException(); + ti.getUpdateService().insertRows(_user, _container, rows, errors, null, getExtraContext()); + if (errors.hasErrors()) + throw errors; + } + catch (Exception e) + { + _log.error("Error adding daily clinical observation orders", e); + } + } + + } + + public void propagateClinicalObs(Map row, String qcstate) throws SQLException + { + Date scheduledDate = ConvertHelper.convert(row.get("scheduledDate"), Date.class); + Date date = ConvertHelper.convert(row.get("date"), Date.class); + String caseid = ConvertHelper.convert(row.get("caseid"), String.class); + String category = ConvertHelper.convert(row.get("category"), String.class); + String id = ConvertHelper.convert(row.get("id"), String.class); + String area = ConvertHelper.convert(row.get("area"), String.class); + String observation = ConvertHelper.convert(row.get("observation"), String.class); + String performedBy = ConvertHelper.convert(row.get("performedBy"), String.class); + String taskid = ConvertHelper.convert(row.get("taskid"), String.class); + + // First we need to get the observation order frequency for this case and category + TableInfo ti = getTableInfo("study", "observation_order"); + SimpleFilter filter = new SimpleFilter(FieldKey.fromString("caseid"), caseid); + filter.addCondition(FieldKey.fromString("category"), category); + TableSelector ts = new TableSelector(ti, PageFlowUtil.set("frequency"), filter, null); + + Map[] orders = ts.getMapArray(); + if (orders.length > 0) + { + Map order = orders[0]; + if (order != null) + { + filter = new SimpleFilter(FieldKey.fromString("category"), category); + filter.addCondition(FieldKey.fromString("caseid"), caseid, CompareType.NEQ_OR_NULL); + filter.addCondition(FieldKey.fromString("Id"), id); + filter.addCondition(FieldKey.fromString("frequency"), order.get("frequency")); + filter.addCondition(FieldKey.fromString("area"), area); + + ts = new TableSelector(ti, PageFlowUtil.set("caseid", "category"), filter, null); + + ts.getMapCollection().forEach(map -> { + String otherCaseId = (String) map.get("caseid"); + try + { + TableInfo obsTi = getTableInfo("study", "clinical_observations"); + SimpleFilter obsFilter = new SimpleFilter(FieldKey.fromString("caseid"), otherCaseId); + obsFilter.addCondition(FieldKey.fromString("category"), category); + obsFilter.addCondition(FieldKey.fromString("area"), area); + obsFilter.addCondition(FieldKey.fromString("scheduledDate"), scheduledDate); + obsFilter.addCondition(FieldKey.fromString("Id"), id); + TableSelector obsTs = new TableSelector(obsTi, PageFlowUtil.set("Id"), obsFilter, null); + if (!obsTs.exists()) + { + Map obsRow = new CaseInsensitiveHashMap<>(); + obsRow.put("caseid", otherCaseId); + obsRow.put("category", category); + obsRow.put("date", date); + obsRow.put("qcstate", qcstate); + obsRow.put("Id", id); + obsRow.put("scheduledDate", scheduledDate); + obsRow.put("area", area); + obsRow.put("observation", observation); + obsRow.put("performedBy", performedBy); + obsRow.put("taskid", taskid); + + List> rows = new ArrayList<>(); + rows.add(obsRow); + + BatchValidationException errors = new BatchValidationException(); + obsTi.getUpdateService().insertRows(_user, _container, rows, errors, null, getExtraContext()); + if (errors.hasErrors()) + throw errors; + } + } + catch (Exception e) + { + _log.error("Error propagating clinical observations", e); + } + }); + } + } + } } \ No newline at end of file diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/table/NIRC_EHRCustomizer.java b/nirc_ehr/src/org/labkey/nirc_ehr/table/NIRC_EHRCustomizer.java index 48641bfb..83c19b49 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/table/NIRC_EHRCustomizer.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/table/NIRC_EHRCustomizer.java @@ -37,11 +37,17 @@ import org.labkey.api.util.StringExpressionFactory; import org.labkey.api.view.ActionURL; import org.labkey.api.view.template.ClientDependency; +import org.labkey.nirc_ehr.NIRC_EHRManager; +import org.labkey.nirc_ehr.dataentry.form.NIRCBulkClinicalFormType; +import org.labkey.nirc_ehr.dataentry.form.NIRCClinicalObservationsFormType; +import org.labkey.nirc_ehr.dataentry.form.NIRCClinicalRoundsFormType; import java.io.IOException; import java.io.Writer; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.List; import java.util.Set; public class NIRC_EHRCustomizer extends AbstractTableCustomizer @@ -87,7 +93,8 @@ public void customize(TableInfo table) addNecropsyReportLink(ti); addNecropsyEnterDataLink(ti); } - else if (matches(ti, "study", "necropsy") || + + if (matches(ti, "study", "necropsy") || matches(ti, "study", "grossPathology") || matches(ti, "study", "tissueDisposition")) { @@ -108,10 +115,16 @@ else if (matches(ti, "study", "necropsy") || { customizeTreatmentOrder(ti); } - else if (matches(table, "study", "clinical_observations")) + + if (matches(table, "study", "clinical_observations") || matches(ti, "study", "observation_order")) { customizeClinicalObservations((AbstractTableInfo) table); } + + if (matches(ti, "study", "observationSchedule")) + { + customizeObservationSchedule(ti); + } } } @@ -935,7 +948,7 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep { if (caseid != null) { - linkAction.addParameter("formType", "Clinical Cases"); + linkAction.addParameter("formType", "Clinical Rounds"); linkAction.addParameter("caseid", caseid); } else @@ -986,4 +999,221 @@ public boolean isEditable() ti.addColumn(col); } } + + private void customizeObservationSchedule(AbstractTableInfo ti) + { + if (ti.getColumn("observationList") == null ) + { + WrappedColumn col = new WrappedColumn(ti.getColumn("observations"), "observationList"); + col.setLabel("Observations"); + col.setDisplayColumnFactory(new DisplayColumnFactory() + { + + @Override + public DisplayColumn createRenderer(final ColumnInfo colInfo) + { + return new DataColumn(colInfo) + { + + @Override + public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + { + String status = (String) getBoundColumn().getValue(ctx); + String stat = status; + if (status != null) + { + List dailies = new ArrayList<>(); + List nonDailies = new ArrayList<>(); + String[] sts = status.split(";"); + + for (String st : sts) + { + if (NIRC_EHRManager.DAILY_CLINICAL_OBS.contains(st) && !dailies.contains(st)) + { + dailies.add(st); + } + else + { + nonDailies.add(st); + } + } + + if (dailies.size() == NIRC_EHRManager.DAILY_CLINICAL_OBS.size()) + { + stat = NIRC_EHRManager.DAILY_CLINICAL_OBS_TITLE; + if (!nonDailies.isEmpty()) + { + stat += "; " + String.join("; ", nonDailies); + } + } + else + { + stat = status; + } + } + + out.write(stat); + } + }; + } + }); + ti.addColumn(col); + } + + if (ti.getColumn("observationRecord") == null ) + { + WrappedColumn col = new WrappedColumn(ti.getColumn("taskid"), "observationRecord"); + col.setLabel("Record Observations"); + col.setDisplayColumnFactory(new DisplayColumnFactory() { + + @Override + public DisplayColumn createRenderer(final ColumnInfo colInfo) + { + return new DataColumn(colInfo){ + + @Override + public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + { + String taskid = (String)getBoundColumn().getValue(ctx); + Date date = (Date)ctx.get("scheduledDate"); + String caseid = (String)ctx.get("caseid"); + String category = (String)ctx.get("type"); + String observationList = (String)ctx.get("observationList"); + String id = (String)ctx.get("id"); + + ActionURL linkAction = new ActionURL("ehr", "dataEntryForm", ti.getUserSchema().getContainer()); + if (!ti.getUserSchema().getContainer().hasPermission(ti.getUserSchema().getUser(), EHRClinicalEntryPermission.class)) + return; + + if (NIRC_EHRManager.DAILY_CLINICAL_OBS_LIST.equals(observationList)) + { + linkAction.addParameter("formType", NIRCClinicalObservationsFormType.NAME); + linkAction.addParameter("id", id); + linkAction.addParameter("caseid", caseid); + linkAction.addParameter("scheduledDate", date.toString()); + } + else + { + if ("Behavior".equals(category)) + { + if (caseid != null) + { + linkAction.addParameter("formType", "Behavior Rounds"); + linkAction.addParameter("caseid", caseid); + } + else + { + linkAction.addParameter("formType", "Bulk Behavior Entry"); + } + } + else if ("Surgery".equals(category)) + { + linkAction.addParameter("formType", "Surgery Rounds"); + linkAction.addParameter("caseid", caseid); + } + else + { + if (caseid != null) + { + linkAction.addParameter("formType", NIRCClinicalRoundsFormType.NAME); + linkAction.addParameter("caseid", caseid); + } + else + { + linkAction.addParameter("formType", NIRCBulkClinicalFormType.NAME); + } + } + + linkAction.addParameter("id", id); + linkAction.addParameter("obsTask", taskid); + linkAction.addParameter("observations", observationList); + linkAction.addParameter("scheduledDate", date.toString()); + } + String returnUrl = new ActionURL("ehr", "animalHistory", ti.getUserSchema().getContainer()).toString() + "#inputType:none&showReport:0&activeReport:observationSchedule"; + linkAction.addParameter("returnUrl", returnUrl); + + String href = linkAction.toString(); + out.write(PageFlowUtil.link("Record Observations").href(href).target("_blank").toString()); + } + + @Override + public void addQueryFieldKeys(Set keys) + { + super.addQueryFieldKeys(keys); + keys.add(getBoundColumn().getFieldKey()); + keys.add(FieldKey.fromString("taskid")); + keys.add(FieldKey.fromString("caseid")); + keys.add(FieldKey.fromString("id")); + keys.add(FieldKey.fromString("observations")); + keys.add(FieldKey.fromString("scheduledDate")); + keys.add(FieldKey.fromString("type")); + } + + @Override + public boolean isSortable() + { + return false; + } + + @Override + public boolean isFilterable() + { + return false; + } + + @Override + public boolean isEditable() + { + return false; + } + }; + } + }); + ti.addColumn(col); + } + + if (ti.getColumn("observationStatus") == null ) + { + WrappedColumn col = new WrappedColumn(ti.getColumn("status"), "observationStatus"); + col.setLabel("Status"); + col.setDisplayColumnFactory(new DisplayColumnFactory() + { + + @Override + public DisplayColumn createRenderer(final ColumnInfo colInfo) + { + return new DataColumn(colInfo) + { + + @Override + public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + { + String status = (String) getBoundColumn().getValue(ctx); + String stat = ""; + if (status != null) + { + String[] sts = status.split(";"); + + for (String st : sts) + { + if (stat.isEmpty() && st.equals("Completed")) + { + stat = "Completed"; + } + + if ("Completed".equals(stat) && !st.equals("Completed")) + { + stat = st; + } + } + } + + out.write(stat); + } + }; + } + }); + ti.addColumn(col); + } + } } diff --git a/nirc_ehr/test/sampledata/nircEHRStudyPolicy.xml b/nirc_ehr/test/sampledata/nircEHRStudyPolicy.xml index 7cd23ba2..7ebd5484 100644 --- a/nirc_ehr/test/sampledata/nircEHRStudyPolicy.xml +++ b/nirc_ehr/test/sampledata/nircEHRStudyPolicy.xml @@ -112,6 +112,12 @@ + + + + + + From f846312d1069cb47087f3e94bc64bc18acd7b0b1 Mon Sep 17 00:00:00 2001 From: Ankur Juneja Date: Sun, 15 Sep 2024 09:31:59 -0700 Subject: [PATCH 3/5] New behavioral animal training data entry form and dataset (#387) --- nirc_ehr/resources/data/editable_lookups.tsv | 3 ++ nirc_ehr/resources/data/lookup_sets.tsv | 3 ++ nirc_ehr/resources/data/lookupsManifest.tsv | 3 ++ .../resources/data/lookupsManifestTest.tsv | 3 ++ .../resources/data/nhp_training_reason.tsv | 6 +++ .../resources/data/nhp_training_result.tsv | 4 ++ nirc_ehr/resources/data/nhp_training_type.tsv | 5 +++ .../resources/queries/study/nhpTraining.js | 1 + .../queries/study/nhpTraining.query.xml | 41 +++++++++++++++++++ .../study/datasets/datasets_manifest.xml | 1 + .../study/datasets/datasets_metadata.xml | 33 +++++++++++++++ .../postgresql/nirc_ehr-24.013-24.014.sql | 8 ++++ .../org/labkey/nirc_ehr/NIRC_EHRModule.java | 3 +- .../form/NIRCAnimalTrainingFormType.java | 24 +++++++++++ 14 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 nirc_ehr/resources/data/nhp_training_reason.tsv create mode 100644 nirc_ehr/resources/data/nhp_training_result.tsv create mode 100644 nirc_ehr/resources/data/nhp_training_type.tsv create mode 100644 nirc_ehr/resources/queries/study/nhpTraining.js create mode 100644 nirc_ehr/resources/queries/study/nhpTraining.query.xml create mode 100644 nirc_ehr/resources/schemas/dbscripts/postgresql/nirc_ehr-24.013-24.014.sql create mode 100644 nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCAnimalTrainingFormType.java diff --git a/nirc_ehr/resources/data/editable_lookups.tsv b/nirc_ehr/resources/data/editable_lookups.tsv index 82aa77aa..fbd664c9 100644 --- a/nirc_ehr/resources/data/editable_lookups.tsv +++ b/nirc_ehr/resources/data/editable_lookups.tsv @@ -67,6 +67,9 @@ necropsy_physical_condition Colony Management Necropsy Physical Condition necropsy_specimen_condition Colony Management Necropsy Specimen Condition necropsy_tissue Colony Management Necropsy Tissue neurologic_types Clinical Neurologic Types Clinical observation fixed values. +nhp_training_reason Behavior NHP Training Reason Behavior training reason values +nhp_training_result Behavior NHP Training Result Behavior training result values +nhp_training_type Behavior NHP Training Type Behavior training type values numeric_unit Colony Management Numeric Unit observation_types Clinical Clin remarks observation types observation_areas Clinical Observation Areas Clinical observation areas. diff --git a/nirc_ehr/resources/data/lookup_sets.tsv b/nirc_ehr/resources/data/lookup_sets.tsv index c6ecaefa..2c39a814 100644 --- a/nirc_ehr/resources/data/lookup_sets.tsv +++ b/nirc_ehr/resources/data/lookup_sets.tsv @@ -58,6 +58,9 @@ necropsy_physical_condition Physical Condition value title necropsy_specimen_condition Specimen Condition value title necropsy_tissue Tissues value title neurologic_types Neurologic Types value title +nhp_training_reason NHP Training Reason value +nhp_training_result NHP Training Result value +nhp_training_type NHP Training Type value numeric_unit Numeric Units value title observation_areas Observation Areas value ocular_problem Ocular Problem value diff --git a/nirc_ehr/resources/data/lookupsManifest.tsv b/nirc_ehr/resources/data/lookupsManifest.tsv index 89a0581e..30eabab6 100644 --- a/nirc_ehr/resources/data/lookupsManifest.tsv +++ b/nirc_ehr/resources/data/lookupsManifest.tsv @@ -64,6 +64,9 @@ necropsy_physical_condition necropsy_specimen_condition necropsy_tissue neurologic_types +nhp_training_reason +nhp_training_result +nhp_training_type numeric_unit observation_areas ocular_problem diff --git a/nirc_ehr/resources/data/lookupsManifestTest.tsv b/nirc_ehr/resources/data/lookupsManifestTest.tsv index b7d3656e..cc8589d6 100644 --- a/nirc_ehr/resources/data/lookupsManifestTest.tsv +++ b/nirc_ehr/resources/data/lookupsManifestTest.tsv @@ -63,6 +63,9 @@ necropsy_physical_condition necropsy_specimen_condition necropsy_tissue neurologic_types +nhp_training_reason +nhp_training_result +nhp_training_type numeric_unit observation_areas ocular_problem diff --git a/nirc_ehr/resources/data/nhp_training_reason.tsv b/nirc_ehr/resources/data/nhp_training_reason.tsv new file mode 100644 index 00000000..f1d97597 --- /dev/null +++ b/nirc_ehr/resources/data/nhp_training_reason.tsv @@ -0,0 +1,6 @@ +value +PI Request +Behavioral Initiated +Clinic +Husbandry +Other \ No newline at end of file diff --git a/nirc_ehr/resources/data/nhp_training_result.tsv b/nirc_ehr/resources/data/nhp_training_result.tsv new file mode 100644 index 00000000..7b240f2f --- /dev/null +++ b/nirc_ehr/resources/data/nhp_training_result.tsv @@ -0,0 +1,4 @@ +value +In-Progress +Successful +Unsuccessful \ No newline at end of file diff --git a/nirc_ehr/resources/data/nhp_training_type.tsv b/nirc_ehr/resources/data/nhp_training_type.tsv new file mode 100644 index 00000000..4398c3a9 --- /dev/null +++ b/nirc_ehr/resources/data/nhp_training_type.tsv @@ -0,0 +1,5 @@ +value +Chair +Present +Physical Therapy +Other \ No newline at end of file diff --git a/nirc_ehr/resources/queries/study/nhpTraining.js b/nirc_ehr/resources/queries/study/nhpTraining.js new file mode 100644 index 00000000..72d57b2b --- /dev/null +++ b/nirc_ehr/resources/queries/study/nhpTraining.js @@ -0,0 +1 @@ +require("ehr/triggers").initScript(this); \ No newline at end of file diff --git a/nirc_ehr/resources/queries/study/nhpTraining.query.xml b/nirc_ehr/resources/queries/study/nhpTraining.query.xml new file mode 100644 index 00000000..c2cabce2 --- /dev/null +++ b/nirc_ehr/resources/queries/study/nhpTraining.query.xml @@ -0,0 +1,41 @@ + + + + + Animal Training + + + + + Training Type + + ehr_lookups + nhp_training_type + value + + + + Reason + + ehr_lookups + nhp_training_reason + value + + + + Result + + ehr_lookups + nhp_training_result + value + + + + Training Staff + + + +
+
+
+
\ No newline at end of file diff --git a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml index 6f69f6f8..435d3405 100644 --- a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml +++ b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_manifest.xml @@ -26,6 +26,7 @@ + diff --git a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml index 9abfc5bf..2743eae5 100644 --- a/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml +++ b/nirc_ehr/resources/referenceStudy/study/datasets/datasets_metadata.xml @@ -1409,4 +1409,37 @@ Observation Orders + + Animal Training + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + urn:ehr.labkey.org/#EndDate + + + varchar + + + varchar + + + varchar + + + varchar + + +
\ No newline at end of file diff --git a/nirc_ehr/resources/schemas/dbscripts/postgresql/nirc_ehr-24.013-24.014.sql b/nirc_ehr/resources/schemas/dbscripts/postgresql/nirc_ehr-24.013-24.014.sql new file mode 100644 index 00000000..e449f657 --- /dev/null +++ b/nirc_ehr/resources/schemas/dbscripts/postgresql/nirc_ehr-24.013-24.014.sql @@ -0,0 +1,8 @@ +SELECT core.executeJavaUpgradeCode('reloadFolder'); + +SELECT core.executeJavaUpgradeCode('importFromTsv;ehr_lookups;lookup_sets;/data/lookup_sets.tsv'); +SELECT core.executeJavaUpgradeCode('importFromTsv;ehr_lookups;editable_lookups;/data/editable_lookups.tsv'); + +SELECT core.executeJavaUpgradeCode('importFromTsv;ehr_lookups;nhp_training_reason;/data/nhp_training_reason.tsv'); +SELECT core.executeJavaUpgradeCode('importFromTsv;ehr_lookups;nhp_training_result;/data/nhp_training_result.tsv'); +SELECT core.executeJavaUpgradeCode('importFromTsv;ehr_lookups;nhp_training_type;/data/nhp_training_type.tsv'); \ No newline at end of file diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java b/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java index 8a0396c3..edbcb4fb 100644 --- a/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java +++ b/nirc_ehr/src/org/labkey/nirc_ehr/NIRC_EHRModule.java @@ -69,7 +69,7 @@ public String getName() @Override public @Nullable Double getSchemaVersion() { - return 24.013; + return 24.014; } @Override @@ -196,6 +196,7 @@ private void registerDataEntry() EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NIRCCageFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NIRCClinicalObservationsFormType.class, this)); EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NIRCClinicalRoundsFormType.class, this)); + EHRService.get().registerFormType(new DefaultDataEntryFormFactory(NIRCAnimalTrainingFormType.class, this)); } @Override diff --git a/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCAnimalTrainingFormType.java b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCAnimalTrainingFormType.java new file mode 100644 index 00000000..95029eab --- /dev/null +++ b/nirc_ehr/src/org/labkey/nirc_ehr/dataentry/form/NIRCAnimalTrainingFormType.java @@ -0,0 +1,24 @@ +package org.labkey.nirc_ehr.dataentry.form; + +import org.labkey.api.ehr.EHRService; +import org.labkey.api.ehr.dataentry.DataEntryFormContext; +import org.labkey.api.module.Module; +import org.labkey.nirc_ehr.dataentry.section.BaseFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCAnimalDetailsFormSection; +import org.labkey.nirc_ehr.dataentry.section.NIRCTaskFormSection; + +import java.util.Arrays; + +public class NIRCAnimalTrainingFormType extends NIRCBaseTaskFormType +{ + public static final String NAME = "Animal Training"; + + public NIRCAnimalTrainingFormType(DataEntryFormContext ctx, Module owner) + { + super(ctx, owner, NAME, NAME, "Behavior", Arrays.asList( + new NIRCTaskFormSection(), + new NIRCAnimalDetailsFormSection(), + new BaseFormSection("study", "nhpTraining", NAME, "ehr-gridpanel", EHRService.FORM_SECTION_LOCATION.Body, true, false) + )); + } +} From 465f6283c64f248345f203c3cf4aa66669126f8a Mon Sep 17 00:00:00 2001 From: Sweta Jewargikar Date: Mon, 16 Sep 2024 13:52:51 -0700 Subject: [PATCH 4/5] Automation test for clinical case workflow updates (#386) --- .../tests.nirc_ehr/NIRC_EHRTest.java | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java b/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java index 5e28137a..41e889a7 100644 --- a/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java +++ b/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java @@ -52,6 +52,7 @@ import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; import java.io.BufferedReader; import java.io.File; @@ -61,6 +62,7 @@ import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; @@ -82,6 +84,7 @@ public class NIRC_EHRTest extends AbstractGenericEHRTest implements PostgresOnly private static String NIRC_BASIC_SUBMITTER_VET_TECH = "vet_tech_bs@nirctest.com"; private static String NIRC_FULL_SUBMITTER_VET_TECH = "vet_tech_fs@nirctest.com"; private static String NIRC_FULL_SUBMITTER_VET = "vet_fs@nirctest.com"; + private static String NIRC_VET_NAME = "vet fs"; private static String deadAnimalId = "D5454"; private static String departedAnimalId = "H6767"; @@ -608,20 +611,50 @@ public void testClinicalCasesWorkflow() setFormElement(Locator.textarea("openRemark"), "Clinical Case WorkFlow - Test"); setFormElement(Locator.textarea("plan"), "Case plan"); setFormElement(Locator.name("Id"), animalId); - setFormElement(Locator.name("date"), LocalDateTime.now().minusDays(6).format(_dateFormat)); + setFormElement(Locator.name("date"), LocalDateTime.now().minusDays(1).format(_dateFormat)); Assert.assertEquals("Performed by is incorrect ", "vet tech fs", getFormElement(Locator.name("performedby"))); //Fill out Clinical Remarks section with Date, Remark - setFormElement(Locator.name("date").index(1), LocalDateTime.now().minusDays(5).format(_dateFormat)); - setFormElement(Locator.textarea("remark"), "Clinical Remarks - Test "); + scrollIntoView(Locator.textarea("remark")); + setFormElement(Locator.name("date").index(1), LocalDateTime.now().minusDays(1).format(_dateFormat)); + _helper.setDataEntryField("remark", "Clinical Remarks - Test"); + waitForTextToDisappear("Remark: WARN: Must enter at least one comment"); Ext4GridRef weight = _helper.getExt4GridForFormSection("Weights"); _helper.addRecordToGrid(weight); weight.setGridCellJS(1, "date", LocalDateTime.now().minusDays(1).format(_dateFormat)); weight.setGridCell(1, "weight", "6.000"); - //'Submit Final' + log("Adding Medications/Treatments Orders"); + Ext4GridRef orderGrid = _helper.getExt4GridForFormSection("Medications/Treatments Orders"); + _helper.addRecordToGrid(orderGrid); + orderGrid.setGridCell(1, "date", LocalDateTime.now().minusDays(1).format(_dateFormat)); + orderGrid.clickDownArrowOnGrid(1, "code"); + orderGrid.setGridCell(1, "code", "Diazepam"); + orderGrid.clickDownArrowOnGrid(1, "frequency"); + orderGrid.setGridCell(1, "frequency", "QID"); + orderGrid.clickDownArrowOnGrid(1, "route"); + orderGrid.setGridCell(1, "route", "IVAG"); + orderGrid.clickDownArrowOnGrid(1, "orderedby"); + orderGrid.setGridCell(1, "orderedby", NIRC_VET_NAME); + orderGrid.completeEdit(); submitForm("Submit Final", "Finalize Form"); + + log("Completing today's Medication Schedule"); + goToEHRFolder(); + waitAndClickAndWait(Locator.linkWithText("Today's Medication Schedule")); + AnimalHistoryPage animalHistoryPage = new AnimalHistoryPage<>(getDriver()); + DataRegionTable scheduleTable = animalHistoryPage.getActiveReportDataRegion(); + Assert.assertEquals("Incorrect number of rows", 4, scheduleTable.getDataRowCount()); + scheduleTable.link(0, "treatmentRecord").click(); + switchToWindow(1); + + waitForText("Remark: WARN: Must enter at least one comment"); + _helper.setDataEntryField("remark", "Clinical Remarks - Treatment complete"); + orderGrid = _helper.getExt4GridForFormSection("Medications/Treatments Given"); + orderGrid.setGridCell(1, "orderedby", NIRC_VET_NAME); + waitForTextToDisappear("Remark: WARN: Must enter at least one comment"); + submitForm("Submit Final", "Finalize"); stopImpersonating(); //Go to NIRC/EHR main page @@ -635,14 +668,17 @@ public void testClinicalCasesWorkflow() AnimalHistoryPage historyPage = new AnimalHistoryPage<>(getDriver()); DataRegionTable activeClinicalCases = historyPage.getActiveReportDataRegion(); activeClinicalCases.link(0, "caseCheck").click(); - switchToWindow(1); + switchToWindow(2); //Fill out Close Date - setFormElement(Locator.name("enddate"), LocalDateTime.now().format(_dateFormat)); + _helper.setDataEntryField("s", "Closing the case"); + waitForTextToDisappear("Subjective: WARN: Must enter at least one comment"); - //Verifying if the form was loaded with all the entered data - weight = _helper.getExt4GridForFormSection("Weights"); - Assert.assertEquals("Weight value entered was not retrived", 1, weight.getRowCount()); + waitForElement(Ext4Helper.Locators.ext4Button("Edit")); + Ext4Helper.Locators.ext4Button("Edit").findElement(getDriver()).click(); + if( !isElementVisible(Locator.name("enddate"))) + Ext4Helper.Locators.ext4Button("Edit").findElement(getDriver()).click(); //click again + setFormElement(Locator.name("enddate"), LocalDateTime.now().format(_dateFormat)); //'Submit Final' submitForm("Submit Final", "Finalize Form"); From 3fa73912f79a70993b4c61e5de3fbf896e931bf5 Mon Sep 17 00:00:00 2001 From: Sweta Jewargikar Date: Mon, 23 Sep 2024 13:17:19 -0700 Subject: [PATCH 5/5] Changing the link text to Today's Medication/Treatment Schedule (#394) Co-authored-by: Marty Pradere --- .../tests.nirc_ehr/NIRC_EHRTest.java | 78 +++++++++---------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java b/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java index 41e889a7..acd34b3a 100644 --- a/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java +++ b/nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java @@ -52,7 +52,6 @@ import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; import java.io.BufferedReader; import java.io.File; @@ -62,7 +61,6 @@ import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; -import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; @@ -642,56 +640,56 @@ public void testClinicalCasesWorkflow() log("Completing today's Medication Schedule"); goToEHRFolder(); - waitAndClickAndWait(Locator.linkWithText("Today's Medication Schedule")); + waitAndClickAndWait(Locator.linkWithText("Today's Medication/Treatment Schedule")); AnimalHistoryPage animalHistoryPage = new AnimalHistoryPage<>(getDriver()); DataRegionTable scheduleTable = animalHistoryPage.getActiveReportDataRegion(); Assert.assertEquals("Incorrect number of rows", 4, scheduleTable.getDataRowCount()); scheduleTable.link(0, "treatmentRecord").click(); switchToWindow(1); - waitForText("Remark: WARN: Must enter at least one comment"); - _helper.setDataEntryField("remark", "Clinical Remarks - Treatment complete"); + waitForText("WARN: The field: Ordered By is required"); orderGrid = _helper.getExt4GridForFormSection("Medications/Treatments Given"); orderGrid.setGridCell(1, "orderedby", NIRC_VET_NAME); - waitForTextToDisappear("Remark: WARN: Must enter at least one comment"); + waitForTextToDisappear("WARN: The field: Ordered By is required"); submitForm("Submit Final", "Finalize"); stopImpersonating(); + // TODO: This will be reimplemented in a current PR, this can than be uncommented. //Go to NIRC/EHR main page - goToEHRFolder(); - impersonate(NIRC_FULL_SUBMITTER_VET); - - //Go to 'Active Clinical Cases' - clickAndWait(Locator.linkWithText("Active Clinical Cases")); - - //Click on 'Case Update' link - AnimalHistoryPage historyPage = new AnimalHistoryPage<>(getDriver()); - DataRegionTable activeClinicalCases = historyPage.getActiveReportDataRegion(); - activeClinicalCases.link(0, "caseCheck").click(); - switchToWindow(2); - - //Fill out Close Date - _helper.setDataEntryField("s", "Closing the case"); - waitForTextToDisappear("Subjective: WARN: Must enter at least one comment"); - - waitForElement(Ext4Helper.Locators.ext4Button("Edit")); - Ext4Helper.Locators.ext4Button("Edit").findElement(getDriver()).click(); - if( !isElementVisible(Locator.name("enddate"))) - Ext4Helper.Locators.ext4Button("Edit").findElement(getDriver()).click(); //click again - setFormElement(Locator.name("enddate"), LocalDateTime.now().format(_dateFormat)); - - //'Submit Final' - submitForm("Submit Final", "Finalize Form"); - - //Go to NIRC/EHR main page - goToEHRFolder(); - clickAndWait(Locator.linkWithText("Active Clinical Cases")); - - //Verify that the case is no longer present/is closed - historyPage = new AnimalHistoryPage<>(getDriver()); - activeClinicalCases = historyPage.getActiveReportDataRegion(); - Assert.assertEquals("No active cases", 0, activeClinicalCases.getDataRowCount()); - stopImpersonating(); +// goToEHRFolder(); +// impersonate(NIRC_FULL_SUBMITTER_VET); +// +// //Go to 'Active Clinical Cases' +// clickAndWait(Locator.linkWithText("Active Clinical Cases")); +// +// //Click on 'Case Update' link +// AnimalHistoryPage historyPage = new AnimalHistoryPage<>(getDriver()); +// DataRegionTable activeClinicalCases = historyPage.getActiveReportDataRegion(); +// activeClinicalCases.link(0, "caseCheck").click(); +// switchToWindow(2); +// +// //Fill out Close Date +// _helper.setDataEntryField("s", "Closing the case"); +// waitForTextToDisappear("Subjective: WARN: Must enter at least one comment"); +// +// waitForElement(Ext4Helper.Locators.ext4Button("Edit")); +// Ext4Helper.Locators.ext4Button("Edit").findElement(getDriver()).click(); +// if( !isElementVisible(Locator.name("enddate"))) +// Ext4Helper.Locators.ext4Button("Edit").findElement(getDriver()).click(); //click again +// setFormElement(Locator.name("enddate"), LocalDateTime.now().format(_dateFormat)); +// +// //'Submit Final' +// submitForm("Submit Final", "Finalize Form"); +// +// //Go to NIRC/EHR main page +// goToEHRFolder(); +// clickAndWait(Locator.linkWithText("Active Clinical Cases")); +// +// //Verify that the case is no longer present/is closed +// historyPage = new AnimalHistoryPage<>(getDriver()); +// activeClinicalCases = historyPage.getActiveReportDataRegion(); +// Assert.assertEquals("No active cases", 0, activeClinicalCases.getDataRowCount()); +// stopImpersonating(); } @Override