Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 43 additions & 29 deletions nirc_ehr/resources/queries/study/arrival.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,21 @@ EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Even

helper.registerArrival(row.Id, row.date);

//Insert or update demographic and birth records
if (!row.rearrival && !helper.isETL() && !helper.isGeneratedByServer() && !helper.isValidateOnly()) {

// this allows demographic records in qcstates other than completed
var extraDemographicsFieldMappings = {
'taskid': row.taskid,
'qcstate': helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId()
}

// null (not undefined) required for call to java trigger helper
row.dam = row['Id/demographics/dam'] || null;
row.sire = row['Id/demographics/sire'] || null;
row.species = row['Id/demographics/species'] || null;
row.birth = row['Id/demographics/birth'] || null;
row.gender = row['Id/demographics/gender'] || null;
row.geographic_origin = row['Id/demographics/geographic_origin'] || null;
row.source = row.sourceFacility || null;
// Project, protocol and housing records are created for rearrivals too: the animal's departure closed the previous ones.
if (!helper.isETL() && !helper.isGeneratedByServer() && !helper.isValidateOnly()) {

if (row.QCStateLabel) {
row.qcstate = helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId();
}

if (row.birth) {
var birthInfo = {
// A rearrival reuses the existing demographics record, so its status is written directly; drafts get the same interim status an arrival draft does.
// The update refreshes the server-side animal cache, so the records opened below validate against this status rather than the departure's.
if (row.rearrival && row.Id && row.QCStateLabel) {
row.calculated_status = (row.QCStateLabel.toUpperCase() === 'IN PROGRESS' || row.QCStateLabel.toUpperCase() === 'REVIEW REQUIRED') ? 'Alive - In Progress' : 'Alive';
helper.getJavaHelper().updateDemographicsRecord([{
Id: row.Id,
date: row.birth,
qcstate: row.qcstate,
taskid: row.taskid,
performedby: row.performedby
}

var birthErrors = triggerHelper.saveBirthRecord(row.Id, birthInfo);
if (birthErrors){
EHR.Server.Utils.addError(scriptErrors, 'birth', birthErrors, 'ERROR');
}
calculated_status: row.calculated_status
}]);
}

if (row.Id && row.date) {
Expand Down Expand Up @@ -100,6 +80,40 @@ EHR.Server.TriggerManager.registerHandlerForQuery(EHR.Server.TriggerManager.Even
EHR.Server.Utils.addError(scriptErrors, 'Id', housingErrors, 'ERROR');
}
}
}

//Insert or update demographic and birth records
if (!row.rearrival && !helper.isETL() && !helper.isGeneratedByServer() && !helper.isValidateOnly()) {

// this allows demographic records in qcstates other than completed
var extraDemographicsFieldMappings = {
'taskid': row.taskid,
'qcstate': helper.getJavaHelper().getQCStateForLabel(row.QCStateLabel).getRowId()
}

// null (not undefined) required for call to java trigger helper
row.dam = row['Id/demographics/dam'] || null;
row.sire = row['Id/demographics/sire'] || null;
row.species = row['Id/demographics/species'] || null;
row.birth = row['Id/demographics/birth'] || null;
row.gender = row['Id/demographics/gender'] || null;
row.geographic_origin = row['Id/demographics/geographic_origin'] || null;
row.source = row.sourceFacility || null;

if (row.birth) {
var birthInfo = {
Id: row.Id,
date: row.birth,
qcstate: row.qcstate,
taskid: row.taskid,
performedby: row.performedby
}

var birthErrors = triggerHelper.saveBirthRecord(row.Id, birthInfo);
if (birthErrors){
EHR.Server.Utils.addError(scriptErrors, 'birth', birthErrors, 'ERROR');
}
}

row.calculated_status = (row.QCStateLabel.toUpperCase() === 'IN PROGRESS' || row.QCStateLabel.toUpperCase() === 'REVIEW REQUIRED') ? 'Alive - In Progress' : 'Alive';

Expand Down
53 changes: 38 additions & 15 deletions nirc_ehr/resources/web/nirc_ehr/model/sources/Rearrival.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ EHR.model.DataModelManager.registerMetadata('Rearrival', {
},
},
acquisitionType: {
allowBlank: false,
columnConfig: {
fixed: true,
width: 150
},
allowBlank: true,
hidden: true,
showInGrid: false
},
CITES: {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason for uppercase?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it's required necessarily but the column itself is uppercase.

allowBlank: true,
hidden: true,
showInGrid: false
},
arrivalType: {
allowBlank: false,
Expand All @@ -43,20 +46,40 @@ EHR.model.DataModelManager.registerMetadata('Rearrival', {
}
},
'cage': {
allowBlank: true,
hidden: true,
showInGrid: false
allowBlank: false,
columnConfig: {
fixed: true,
width: 200
},
},
project: {
allowBlank: true,
hidden: true,
showInGrid: false
xtype: 'combo',
columnConfig: {
width: 150
},
lookup: {
schemaName: 'ehr',
queryName: 'project',
keyColumn: 'project',
columns: 'project,name',
filterArray: [
LABKEY.Filter.create('isActive', true, LABKEY.Filter.Types.EQUAL),
]
},
allowBlank: false
},
arrivalProtocol: {
allowBlank: true,
hidden: true,
showInGrid: false
allowBlank: false,
columnConfig: {
width: 200
},
lookup: {
schemaName: 'ehr',
queryName: 'activeProtocols',
keyColumn: 'protocol',
columns: 'protocol,title'
},
},
}
}
});
});
68 changes: 68 additions & 0 deletions nirc_ehr/test/src/org.labkey.test/tests.nirc_ehr/NIRC_EHRTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,74 @@ public void testArrivalForm()
verifyOrchardFileGenerated(arrivedAnimal);
}

@Test
public void testRearrivalForm() throws Exception
{
String rearrivedAnimal = getExpectedAnimalIDCasing("R7373");
LocalDateTime now = LocalDateTime.now();

goToEHRFolder();

log("Seeding an animal that has left the center");
for (String query : List.of("arrival", "departure", "assignment", "protocolAssignment", "housing", "demographics"))
getApiHelper().deleteAllRecords("study", query, new Filter("Id", rearrivedAnimal));

// The departed status is seeded straight onto demographics because a departure does not recalculate
// calculated_status in this module, so inserting one alone would leave the animal alive.
String[] demographicsFields = {"Id", "Species", "Birth", "Gender", "date", "calculated_status", "objectid", "performedby"};
Object[][] demographicsData = {{rearrivedAnimal, "Rhesus", now.minusDays(30).toString(), getMale(), new Date(), "Shipped", UUID.randomUUID().toString(), 1004}};
getApiHelper().doSaveRows(DATA_ADMIN.getEmail(), getApiHelper().prepareInsertCommand("study", "demographics", "lsid", demographicsFields, demographicsData), getExtraContext());

InsertRowsCommand departure = new InsertRowsCommand("study", "departure");
departure.addRow(Map.of("Id", rearrivedAnimal, "date", now.minusDays(2), "destination", "Oregon NPRC", "performedby", 1004));
departure.execute(getApiHelper().getConnection(), getContainerPath());

gotoEnterData();
waitAndClickAndWait(Locator.linkWithText("Rearrivals"));
lockForm();

Ext4GridRef rearrivals = _helper.getExt4GridForFormSection("Rearrivals");
_helper.addRecordToGrid(rearrivals);

log("A rearrival collects project, protocol and location, and does not collect acquisition type or CITES");
Assert.assertTrue("Project should be on the Rearrival form", rearrivals.isColumnPresent("project", true));
Assert.assertTrue("Protocol should be on the Rearrival form", rearrivals.isColumnPresent("arrivalProtocol", true));
Assert.assertTrue("Location should be on the Rearrival form", rearrivals.isColumnPresent("cage", true));
Assert.assertFalse("Acquisition type should not be on the Rearrival form", rearrivals.isColumnPresent("acquisitionType", true));
Assert.assertFalse("CITES should not be on the Rearrival form", rearrivals.isColumnPresent("CITES", true));

rearrivals.setGridCellJS(1, "date", now.minusDays(1).format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT_STRING)));
rearrivals.setGridCell(1, "arrivalType", "Non-quarantine Arrival");
rearrivals.setGridCell(1, "Id", rearrivedAnimal);
rearrivals.setGridCell(1, "cage", "C1");
rearrivals.setGridCell(1, "project", "640991");
rearrivals.setGridCell(1, "arrivalProtocol", "dummyprotocol");
rearrivals.setGridCell(1, "sourceFacility", "BIOQUAL, Inc.");
submitForm("Submit Final", "Finalize");

goToSchemaBrowser();
DataRegionTable table = viewQueryData("study", "arrival");
table.setFilter("Id", "Equals", rearrivedAnimal);
CustomizeView view = table.openCustomizeGrid();
view.addColumn("cage");
view.addColumn("project");
view.addColumn("arrivalProtocol");
view.applyCustomView();
Assert.assertEquals("Invalid Rearrival record", Arrays.asList("C1"), table.getRowDataAsText(0, "cage"));
Assert.assertEquals("Invalid Rearrival record", Arrays.asList("640991"), table.getRowDataAsText(0, "project"));
Assert.assertEquals("Invalid Rearrival record", Arrays.asList("dummyprotocol"), table.getRowDataAsText(0, "arrivalProtocol"));

log("The rearrival opens the assignment, protocol assignment and housing records that the departure closed");
verifyRowCreated("study", "assignment", rearrivedAnimal, 1);
verifyRowCreated("study", "protocolAssignment", rearrivedAnimal, 1);
verifyRowCreated("study", "housing", rearrivedAnimal, 1);

log("The rearrived animal is alive again");
List<Map<String, Object>> rows = executeSelectRowCommand("study", "demographics", ContainerFilter.Current, "/" + getContainerPath(), List.of(new Filter("Id", rearrivedAnimal))).getRows();
assertEquals("Expected one demographics record for the rearrived animal", 1, rows.size());
assertEquals("Rearrived animal should be alive", "Alive", rows.getFirst().get("calculated_status"));
}

@Test
public void testBirthForm()
{
Expand Down