diff --git a/ONPRC_EHR_ComplianceDB/resources/views/employeeDetailsPublic.html b/ONPRC_EHR_ComplianceDB/resources/views/employeeDetailsPublic.html new file mode 100644 index 000000000..fd1dbddf8 --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/views/employeeDetailsPublic.html @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/ONPRC_EHR_ComplianceDB/resources/views/employeeDetailsPublic.view.xml b/ONPRC_EHR_ComplianceDB/resources/views/employeeDetailsPublic.view.xml new file mode 100644 index 000000000..2d2c973a7 --- /dev/null +++ b/ONPRC_EHR_ComplianceDB/resources/views/employeeDetailsPublic.view.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/onprc_billingpublic/resources/queries/onprc_billing_public/NIHIndustryRates/.qview.xml b/onprc_billingpublic/resources/queries/onprc_billing_public/NIHIndustryRates/.qview.xml index a473db037..684af65eb 100644 --- a/onprc_billingpublic/resources/queries/onprc_billing_public/NIHIndustryRates/.qview.xml +++ b/onprc_billingpublic/resources/queries/onprc_billing_public/NIHIndustryRates/.qview.xml @@ -6,52 +6,51 @@ - + - + - + - + - + - + - + - + - + - diff --git a/onprc_billingpublic/resources/queries/onprc_billing_public/NIHRateSheet/.qview.xml b/onprc_billingpublic/resources/queries/onprc_billing_public/NIHRateSheet/.qview.xml index dfe378d46..cc9151e73 100644 --- a/onprc_billingpublic/resources/queries/onprc_billing_public/NIHRateSheet/.qview.xml +++ b/onprc_billingpublic/resources/queries/onprc_billing_public/NIHRateSheet/.qview.xml @@ -6,52 +6,51 @@ - + - + - + - + - + - + - + - + - + - diff --git a/onprc_billingpublic/resources/queries/onprc_billing_public/NIHRates_ReducedFA/.qview.xml b/onprc_billingpublic/resources/queries/onprc_billing_public/NIHRates_ReducedFA/.qview.xml index a21a4dfe7..cdd6ab9a0 100644 --- a/onprc_billingpublic/resources/queries/onprc_billing_public/NIHRates_ReducedFA/.qview.xml +++ b/onprc_billingpublic/resources/queries/onprc_billing_public/NIHRates_ReducedFA/.qview.xml @@ -6,52 +6,51 @@ - + - + - + - + - + - + - + - + - + - diff --git a/onprc_ehr/resources/queries/ehr_lookups/cageReview.sql b/onprc_ehr/resources/queries/ehr_lookups/cageReview.sql index ab21a94d5..38007587f 100644 --- a/onprc_ehr/resources/queries/ehr_lookups/cageReview.sql +++ b/onprc_ehr/resources/queries/ehr_lookups/cageReview.sql @@ -42,6 +42,7 @@ SELECT t.totalWeightExempt, t.totalHeightExempt + FROM ( SELECT @@ -68,6 +69,8 @@ SELECT sum(CASE WHEN t0.weightExemption IS NULL THEN 0 ELSE 1 END) as totalWeightExempt, count(t0.heightExemption) as totalHeightExempt + + FROM ( SELECT @@ -82,11 +85,14 @@ SELECT group_concat(c1.height) as heights, f.heightExemption, CASE + WHEN hf.Id is not null AND c1.height >= pc.cage_type.height THEN 'ERROR: According to the monkeys weight-- it needs a height step taller than required.' + WHEN hf.Id is not null AND c1.height < pc.cage_type.height THEN 'NOTE: According to the monkeys weight-- it needs a height step taller than required.' WHEN (pc.cage_type.height < c1.height AND f.heightExemption IS NULL) THEN ('ERROR: Insufficient height, ' || h.id ||' needs at least: ' || cast(c1.height AS varchar(50))) WHEN (pc.cage_type.height < c1.height AND f.heightExemption IS NOT NULL) THEN cast(('NOTE: Height Exemption: ' || h.Id) as varchar(500)) ELSE null END as heightStatus, - wf.weightExemption + wf.weightExemption, + hf.height_error FROM ehr_lookups.connectedCages pc @@ -98,17 +104,27 @@ LEFT JOIN ( f.id, min(f.flag.value) as heightExemption FROM study.flags f - WHERE f.isActive = true AND f.flag.category = 'Caging Note' and f.flag.description like '%exempt%' + WHERE f.isActive = true AND f.flag.category = 'Caging Note' and (f.flag.description like '%height-exempt%' or f.flag.description like '%Medical-exempt%') GROUP BY f.Id ) f on (f.Id = h.Id) ---weight flags + --height flags +LEFT JOIN ( + SELECT + f.id, + min(f.flag.value) as height_error + FROM study.flags f + WHERE f.isActive = true AND f.flag.category = 'Caging Note' and (f.flag.description like '%height-error%') + GROUP BY f.Id +) hf on (hf.Id = h.Id) + +---weight flags LEFT JOIN ( SELECT f.id, min(f.flag.value) as weightExemption FROM study.flags f - WHERE f.isActive = true AND f.flag.category = 'Caging Note' and f.flag.description like '%exempt%' + WHERE f.isActive = true AND f.flag.category = 'Caging Note' and (f.flag.description like '%weight-exempt%' or f.flag.description like '%Medical-exempt%') GROUP BY f.Id ) wf on (wf.Id = h.Id) diff --git a/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js b/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js index d382b863b..30a298a30 100644 --- a/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js +++ b/onprc_ehr/resources/scripts/onprc_ehr/onprc_triggers.js @@ -1256,85 +1256,118 @@ exports.init = function(EHR){ } } }); + + //Added by Kollil, April 2026 + function toDateOnly(val) { + if (!val) + return null; + + // row.date object + if (typeof val === 'object' && val.time) { + var d = new Date(val.time); + return new Date(d.getFullYear(), d.getMonth(), d.getDate()); + } + + // date strings like "2026-04-20 00:00:00.000" + var s = String(val).split(' ')[0]; // keep only YYYY-MM-DD + var parts = s.split('-'); + if (parts.length !== 3) + return null; + + return new Date(Number(parts[0]), Number(parts[1]) - 1, Number(parts[2])); + } + // Added 10-17-2025 R. Blasa EHR.Server.TriggerManager.unregisterAllHandlersForQueryNameAndEvent('study', 'assignment', EHR.Server.TriggerManager.Events.BEFORE_UPSERT); - EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'assignment', function(helper, scriptErrors, row, oldRow){ - if (!helper.isETL()){ + EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Events.BEFORE_UPSERT, 'study', 'assignment', function(helper, scriptErrors, row, oldRow) { + if (!helper.isETL()) { //note: the the date field is handled above by removeTimeFromDate EHR.Server.Utils.removeTimeFromDate(row, scriptErrors, 'enddate'); EHR.Server.Utils.removeTimeFromDate(row, scriptErrors, 'projectedRelease'); } - //check number of allowed animals at assign/approve time if (!helper.isETL() && !helper.isQuickValidation() && helper.doStandardProtocolCountValidation() && //this is designed to always perform the check on imports, but also updates where the Id was changed - !(oldRow && oldRow.Id && oldRow.Id==row.Id) && + !(oldRow && oldRow.Id && oldRow.Id == row.Id) && row.Id && row.project && row.date - ){ + ) { var assignmentsInTransaction = helper.getProperty('assignmentsInTransaction'); assignmentsInTransaction = assignmentsInTransaction || []; var msgs = helper.getJavaHelper().verifyProtocolCounts(row.Id, row.project, assignmentsInTransaction); - if (msgs){ + if (msgs) { msgs = msgs.split("<>"); - for (var i=0;i row.enddatefinalized.getTime()){ - row.enddatefinalized = row.enddate; - } + // we want to record the date a record was marked endded, in addition to the actual end itself + // NOTE: we only do this when both enddate and releaseType are entered + if (!row.enddatefinalized && row.enddate && row.releaseCondition && EHR.Server.Security.getQCStateByLabel(row.QCStateLabel).PublicData) { + //note: if ended in the future, defer to that date + row.enddatefinalized = new Date(); + if (row.enddate.getTime() > row.enddatefinalized.getTime()) { + row.enddatefinalized = row.enddate; } + } - //check for condition downgrade for assign condition - if (!helper.isETL() && row.Id && row.assignCondition){ - var msg = triggerHelper.checkForConditionDowngrade(row.Id, row.date, row.assignCondition); - if (msg){ - EHR.Server.Utils.addError(scriptErrors, 'assignCondition', msg, 'INFO'); - } + //check for condition downgrade for assign condition + if (!helper.isETL() && row.Id && row.assignCondition) { + var msg = triggerHelper.checkForConditionDowngrade(row.Id, row.date, row.assignCondition); + if (msg) { + EHR.Server.Utils.addError(scriptErrors, 'assignCondition', msg, 'INFO'); } + } - //check for condition downgrade for assign condition - if (!helper.isETL() && row.Id && row.date && row.assignCondition){ - var msg = triggerHelper.checkForConditionDowngrade(row.Id, row.date, row.assignCondition); - if (msg){ - EHR.Server.Utils.addError(scriptErrors, 'assignCondition', msg, 'INFO'); - } + //check for condition downgrade for assign condition + if (!helper.isETL() && row.Id && row.date && row.assignCondition) { + var msg = triggerHelper.checkForConditionDowngrade(row.Id, row.date, row.assignCondition); + if (msg) { + EHR.Server.Utils.addError(scriptErrors, 'assignCondition', msg, 'INFO'); } + } + + //Added by Kollil, April 2026. Refer to ticket # 13807 + if (row.project && row.date) { + var projectEndDate = triggerHelper.getProjectEndDate(row.project); //helper.getJavaHelper().getProjectEndDate(row.project); + var assignmentDate = toDateOnly(row.date); + var endDate = toDateOnly(projectEndDate); + + if (assignmentDate && endDate && assignmentDate.getTime() > endDate.getTime()) { + // console.log('4.5 DEBUG assignmentDate=' + assignmentDate); + EHR.Server.Utils.addError(scriptErrors, 'project', 'The assignment start date occurs after the end date of the selected center project. Please review the assignment date and confirm!', 'WARN'); + + } + } + }); //Added 10-5-2022 R.Blasa diff --git a/onprc_ehr/resources/views/printRoom.html b/onprc_ehr/resources/views/printRoom.html index 55f2aa8a8..01211fcf8 100644 --- a/onprc_ehr/resources/views/printRoom.html +++ b/onprc_ehr/resources/views/printRoom.html @@ -50,6 +50,7 @@ foundCages = true; Ext4.create('Ext.panel.Panel', { border: false, + width: 1450, defaults: { border: false }, @@ -63,7 +64,7 @@ } else { // Hack to improve printing in Chrome - if (Ext4.isChrome) { Ext4.get(webpart.wrapperDivId).setStyle({zoom: '150%'}); }; + if (Ext4.isChrome) { Ext4.get(webpart.wrapperDivId).setStyle({zoom: '110%'}); }; } }, this); diff --git a/onprc_ehr/resources/web/onprc_ehr/model/sources/BehaviorDefaults.js b/onprc_ehr/resources/web/onprc_ehr/model/sources/BehaviorDefaults.js index 5207f3b7b..eada6c102 100644 --- a/onprc_ehr/resources/web/onprc_ehr/model/sources/BehaviorDefaults.js +++ b/onprc_ehr/resources/web/onprc_ehr/model/sources/BehaviorDefaults.js @@ -117,7 +117,8 @@ EHR.model.DataModelManager.registerMetadata('BehaviorDefaults', { }, category: { lookup: { - filterArray: [LABKEY.Filter.create('category', 'Behavior')] + filterArray: [LABKEY.Filter.create('category', 'Behavior'), + LABKEY.Filter.create('value', 'Behaviors',LABKEY.Filter.Types.NEQ)] } } } diff --git a/onprc_ehr/resources/web/onprc_ehr/panel/RoomLayoutPanel.js b/onprc_ehr/resources/web/onprc_ehr/panel/RoomLayoutPanel.js index 1dd9304b0..b331c6582 100644 --- a/onprc_ehr/resources/web/onprc_ehr/panel/RoomLayoutPanel.js +++ b/onprc_ehr/resources/web/onprc_ehr/panel/RoomLayoutPanel.js @@ -184,15 +184,15 @@ Ext4.define('ONPRC.panel.RoomLayoutPanel', { var rooms = Ext4.Object.getKeys(roomMap).sort(); var dividerWidth = 3; - var height = 115; - var cageWidth = 51; //Modified: 10-15-2020 + var height = 75; + var cageWidth = 60; var hasCages = false; Ext4.each(rooms, function(room, roomIdx){ if (roomIdx == 0 && !config.printMode){ toAdd.push(ONPRC.panel.RoomLayoutPanel.getButtonCfgs(config)); toAdd.push({ - style: 'margin-bottom: 20px;', + style: 'margin-bottom: 5px;', border: false }); } @@ -244,7 +244,7 @@ Ext4.define('ONPRC.panel.RoomLayoutPanel', { border: false }); - //Modified: 8-19-2019 R. Blasa Added Divider Legends Not eeded at this time + //Modified: 8-19-2019 R. Blasa Added Divider Legends Not needed at this time currentSection.push({ //Modified: 4/3/2023 R.Blasa diff --git a/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessing.xlsx b/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessing.xlsx deleted file mode 100644 index 9979a28d5..000000000 Binary files a/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessing.xlsx and /dev/null differ diff --git a/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessingTemplate.xlsx b/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessingTemplate.xlsx old mode 100644 new mode 100755 index bae51e026..66f764b22 Binary files a/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessingTemplate.xlsx and b/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessingTemplate.xlsx differ diff --git a/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessingTemplate_TPR_Master.xlsx b/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessingTemplate_TPR_Master.xlsx old mode 100644 new mode 100755 index d3affcd46..a3ff5ddee Binary files a/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessingTemplate_TPR_Master.xlsx and b/onprc_ehr/resources/web/onprc_ehr/templates/ClinicalProcessingTemplate_TPR_Master.xlsx differ diff --git a/onprc_ehr/resources/web/onprc_ehr/window/ClinicalMassProcessing.js b/onprc_ehr/resources/web/onprc_ehr/window/ClinicalMassProcessing.js index 74cb01ae1..9633f508b 100644 --- a/onprc_ehr/resources/web/onprc_ehr/window/ClinicalMassProcessing.js +++ b/onprc_ehr/resources/web/onprc_ehr/window/ClinicalMassProcessing.js @@ -305,6 +305,8 @@ Ext4.define('ONPRC_EHR.window.ClinicalProcessingWindow', { {snomedcode = 'F-31030'} if (row[7]== 3 ) {snomedcode = 'F-31040'} + if (row[7]== 'No' ) + {snomedcode = 'F-30980'} var obj = { Id: id, date: this.getTime(date, times, errors, rowIdx), diff --git a/onprc_ehr/resources/web/onprc_ehr/window/ClinicalMassProcessing_TPR.js b/onprc_ehr/resources/web/onprc_ehr/window/ClinicalMassProcessing_TPR.js index 3c7d37472..f883a9b76 100644 --- a/onprc_ehr/resources/web/onprc_ehr/window/ClinicalMassProcessing_TPR.js +++ b/onprc_ehr/resources/web/onprc_ehr/window/ClinicalMassProcessing_TPR.js @@ -420,6 +420,8 @@ Ext4.define('ONPRC_EHR.window.ClinicalProcessingTPRWindow', { {snomedcode = 'F-31030'} if (row[10]== 3 ) {snomedcode = 'F-31040'} + if (row[10]== 'No' ) + {snomedcode = 'F-30980'} var obj = { Id: id, date: this.getTime(date, times, errors, rowIdx), diff --git a/onprc_ehr/src/org/labkey/onprc_ehr/query/ONPRC_EHRTriggerHelper.java b/onprc_ehr/src/org/labkey/onprc_ehr/query/ONPRC_EHRTriggerHelper.java index af711cba9..de49e9cc6 100644 --- a/onprc_ehr/src/org/labkey/onprc_ehr/query/ONPRC_EHRTriggerHelper.java +++ b/onprc_ehr/src/org/labkey/onprc_ehr/query/ONPRC_EHRTriggerHelper.java @@ -2021,6 +2021,33 @@ public boolean requiresAssistingStaff(Integer procedureId) return "Surgery".equals(category); } + //Added by Kollil + //Date: Apr 2026 + public Date getProjectEndDate(Object projectId) + { + if (projectId == null) + return null; + + int pid; + if (projectId instanceof Number) + pid = ((Number) projectId).intValue(); + else + pid = Integer.parseInt(projectId.toString()); + + UserSchema ehrSchema = QueryService.get().getUserSchema(_user, _container, "ehr"); + if (ehrSchema == null) + return null; + + TableInfo ti = ehrSchema.getTable("project"); + if (ti == null) + return null; + + SimpleFilter filter = new SimpleFilter(FieldKey.fromString("project"), pid); + TableSelector ts = new TableSelector(ti, Collections.singleton("enddate"), filter, null); + + return ts.getObject(Date.class); + } + public String getSpeciesForDam(String dam) { return new TableSelector(getTableInfo("study", "demographics"), PageFlowUtil.set("species"), new SimpleFilter(FieldKey.fromString("Id"), dam), null).getObject(String.class); diff --git a/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java b/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java index 1614ab36e..92589d531 100644 --- a/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java +++ b/onprc_ehr/test/src/org/labkey/test/tests/onprc_ehr/ONPRC_EHRTest.java @@ -71,6 +71,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.function.Function; import static org.junit.Assert.assertEquals; @@ -556,6 +557,29 @@ public void testArrivalApi() throws Exception Assert.assertEquals(1, demographicsSelect.execute(getApiHelper().getConnection(), getContainerPath()).getRowCount().intValue()); } + @Test + public void testSubmitButtonsDisabledDuringValidation() throws Exception + { + List allIds = createTemporaryValidationAnimals(30); + + try + { + log("Bulk adding animals in treatment orders for temporary test animals"); + _helper.goToTaskForm("Medications/Diet", false); + Ext4GridRef treatmentGrid = _helper.getExt4GridForFormSection("Medication/Treatment Orders"); + addBatchIdsToGrid(treatmentGrid, allIds); + + assertActionsDisabledDuringValidation(); + + treatmentGrid.waitForRowCount(allIds.size()); + _helper.discardForm(); + } + finally + { + deleteTemporaryValidationAnimals(allIds); + } + } + @Test public void testCustomActions() throws Exception { @@ -1102,8 +1126,9 @@ public void testExamEntry() throws Exception Assert.assertEquals(remark, bloodGrid.getFieldValue(3, "remark")); Assert.assertEquals(remark, bloodGrid.getFieldValue(4, "remark")); - waitAndClickAndWait(_helper.getDataEntryButton("Save & Close")); - waitForElement(Locator.tagWithText("a", "Enter New Data")); + waitForDataEntryButtonEnabled("Save & Close", WAIT_FOR_PAGE * 2); + waitAndClick(_helper.getDataEntryButton("Save & Close")); + waitForElement(Locator.tagWithText("a", "Enter New Data"), WAIT_FOR_PAGE * 2); } @Test @@ -1487,6 +1512,9 @@ public void testPathology() //test SNOMED codes _ext4Helper.clickExt4Tab("Histologic Findings"); Ext4GridRef histologyGrid = _helper.getExt4GridForFormSection("Histologic Findings"); + // The custom "Add Record" handler returns early until the tab's grid store finishes loading. + waitFor(() -> (Boolean)histologyGrid.getFnEval("return !!this.store && (!this.store.hasLoaded || this.store.hasLoaded());"), + "Histologic Findings grid store did not finish loading", WAIT_FOR_JAVASCRIPT); _helper.addRecordToGrid(histologyGrid, "Add Record"); scrollIntoView(histologyGrid.getCell(1,7), true); waitAndClick(histologyGrid.getCell(1, 7)); @@ -1565,7 +1593,9 @@ public void testPathology() waitForElementToDisappear(deathWindow, 20000); //saving can take longer than default 10 seconds waitForElementToDisappear(Locator.tagContainingText("div", "Saving Changes...").notHidden()); - waitAndClickAndWait(_helper.getDataEntryButton("Save & Close")); + waitForDataEntryButtonEnabled("Save & Close", WAIT_FOR_PAGE * 2); + waitAndClick(_helper.getDataEntryButton("Save & Close")); + waitForElement(Locator.tagWithText("a", "Enter New Data"), WAIT_FOR_PAGE * 2); //make new necropsy, copy from previous _helper.goToTaskForm("Necropsy", false); @@ -1970,6 +2000,107 @@ private void setNecropsyFormElement(String id, String value) assertEquals(value, getFormElement(loc)); } + private void addBatchIdsToGrid(Ext4GridRef grid, List ids) + { + grid.clickTbarButton("Add Batch"); + waitForElement(Ext4Helper.Locators.window("Choose Animals")); + Ext4FieldRef.getForLabel(this, "Id(s)").setValue(StringUtils.join(ids, ";")); + + waitAndClick(Ext4Helper.Locators.window("Choose Animals").append(Ext4Helper.Locators.ext4Button("Submit"))); + grid.waitForRowCount(ids.size()); + } + + private void assertActionsDisabledDuringValidation() + { + List buttonTexts = Arrays.asList("Save Draft", "Save & Close", "Submit For Review", "Submit Final"); + List menuItemTexts = Arrays.asList("Submit And Reload", "Force Submit"); + Locator.XPathLocator validationIndicator = Locator.tagContainingText("span", "Validating...").notHidden(); + waitFor(() -> !validationIndicator.findElements(getDriver()).isEmpty(), + "Validation indicator never appeared", WAIT_FOR_PAGE); + + for (String buttonText : buttonTexts) + { + List buttons = _ext4Helper.componentQuery("button[text='" + buttonText + "']", Ext4CmpRef.class); + if (!buttons.isEmpty()) + { + waitFor(() -> Boolean.TRUE.equals(buttons.get(0).getEval("isDisabled() == arguments[0]", true)), + buttonText + " did not become disabled during validation", WAIT_FOR_PAGE); + } + } + + waitAndClick(_helper.getDataEntryButton("More Actions")); + waitForElement(Ext4Helper.Locators.menu().notHidden()); + for (String menuItemText : menuItemTexts) + { + waitForElement(Ext4Helper.Locators.menuItemDisabled(menuItemText).notHidden()); + } + waitAndClick(_helper.getDataEntryButton("More Actions")); + waitForElementToDisappear(Ext4Helper.Locators.menu().notHidden()); + + waitFor(() -> validationIndicator.findElements(getDriver()).isEmpty(), + "Validation indicator did not disappear", WAIT_FOR_PAGE * 2); + waitForText(WAIT_FOR_PAGE * 2, "WARN"); + waitForText(WAIT_FOR_PAGE * 2, "ERROR"); + } + + private List createTemporaryValidationAnimals(int count) throws Exception + { + String seed = Long.toString(System.currentTimeMillis()); + seed = seed.substring(Math.max(0, seed.length() - 6)); + + String[] species = {"Rhesus", "Cynomolgus", "Marmoset"}; + String[] fields = {"Id", "Species", "Birth", "Gender", "date", "calculated_status", "objectid"}; + Object[][] data = new Object[count][]; + List ids = new ArrayList<>(); + + for (int i = 0; i < count; i++) + { + String id = "VAL" + seed + String.format("%02d", i + 1); + ids.add(id); + data[i] = new Object[]{ + id, + species[i % species.length], + new Date().toString(), + i % 2 == 0 ? getMale() : getFemale(), + new Date(), + "Alive", + UUID.randomUUID().toString() + }; + } + + getApiHelper().deleteAllRecords("study", "demographics", new Filter("Id", StringUtils.join(ids, ";"), Filter.Operator.IN)); + getApiHelper().doSaveRows(DATA_ADMIN.getEmail(), + getApiHelper().prepareInsertCommand("study", "demographics", "lsid", fields, data), + getExtraContext()); + cacheIds(ids); + + return ids; + } + + private void deleteTemporaryValidationAnimals(List ids) throws Exception + { + if (ids.isEmpty()) + { + return; + } + + getApiHelper().deleteAllRecords("study", "demographics", new Filter("Id", StringUtils.join(ids, ";"), Filter.Operator.IN)); + } + + private void waitForDataEntryButtonEnabled(String buttonText, int timeout) + { + waitFor(() -> { + List buttons = _ext4Helper.componentQuery("button[text='" + buttonText + "']", Ext4CmpRef.class); + if (buttons.isEmpty()) + { + return false; + } + + return Boolean.TRUE.equals(buttons.get(0).getEval("isDisabled() == arguments[0]", false)); + }, + "Button did not become enabled: " + buttonText, timeout); + } + @Override protected String getAnimalHistoryPath() {