diff --git a/mcc/package-lock.json b/mcc/package-lock.json
index d8baa823b..68c3ae536 100644
--- a/mcc/package-lock.json
+++ b/mcc/package-lock.json
@@ -11317,12 +11317,9 @@
"dev": true
},
"node_modules/json5": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
- "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
- "dependencies": {
- "minimist": "^1.2.5"
- },
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"bin": {
"json5": "lib/cli.js"
},
@@ -11510,9 +11507,9 @@
}
},
"node_modules/loader-utils/node_modules/json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
- "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dependencies": {
"minimist": "^1.2.0"
},
@@ -24057,12 +24054,9 @@
"dev": true
},
"json5": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
- "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
- "requires": {
- "minimist": "^1.2.5"
- }
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
},
"jsonfile": {
"version": "6.1.0",
@@ -24217,9 +24211,9 @@
},
"dependencies": {
"json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
- "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"requires": {
"minimist": "^1.2.0"
}
diff --git a/mcc/resources/data/death_cause.tsv b/mcc/resources/data/death_cause.tsv
new file mode 100644
index 000000000..a7fe3a6b7
--- /dev/null
+++ b/mcc/resources/data/death_cause.tsv
@@ -0,0 +1,26 @@
+value title category description sort_order date_disabled
+Spontaneous Death 1
+Sudden Infant Death 5
+Accidental Death 13
+Death Due to Fight 14
+Acute Surgical Death 6
+Postoperative Death 7
+Dead On Arrival 15
+Unplanned Experimental Death 8
+Perinatal Death 2
+Postpartum Death 9
+Death in Quarantine 12
+Undetermined Cause 10
+Unclassified Cause 11
+Abortion ( < 130 days gestation ) 17
+Spontaneous Death, Experimental subject 22
+Neonatal death (<28 days of age, breathed once) 28
+Spontaneous Death in quarantine 24
+Stillbirth ( > 130 days gestation, never breathed) 16
+Cause of Death Unknown 99
+EUTHANASIA, EXPERIMENTAL 3
+EUTHANASIA, NONEXPERIMENTAL 4
+EUTHANASIA, QUARANTINE 3
+Medical Termination 30
+Miscarriage 32
+Biochemical Pregnancy 35
diff --git a/mcc/resources/referenceStudy/study/datasets/datasets_manifest.xml b/mcc/resources/referenceStudy/study/datasets/datasets_manifest.xml
index b6f22d8d5..bab0de73a 100644
--- a/mcc/resources/referenceStudy/study/datasets/datasets_manifest.xml
+++ b/mcc/resources/referenceStudy/study/datasets/datasets_manifest.xml
@@ -37,13 +37,13 @@
-
+
-
+
diff --git a/mcc/resources/views/populateData.html b/mcc/resources/views/populateData.html
index b9628b62e..d9337b2ef 100644
--- a/mcc/resources/views/populateData.html
+++ b/mcc/resources/views/populateData.html
@@ -178,6 +178,13 @@
schemaName: 'ehr_lookups',
queryName: 'conc_units',
pk: 'rowid'
+ },{
+ label: 'Death Cause',
+ populateFn: 'populateFromFile',
+ moduleName: 'mcc',
+ schemaName: 'ehr_lookups',
+ queryName: 'death_cause',
+ pk: 'rowid'
},{
label: 'Dosage Units',
populateFn: 'populateFromFile',
diff --git a/mcc/resources/web/mcc/panel/MccImportPanel.js b/mcc/resources/web/mcc/panel/MccImportPanel.js
index d3a9b20ca..f2a385072 100644
--- a/mcc/resources/web/mcc/panel/MccImportPanel.js
+++ b/mcc/resources/web/mcc/panel/MccImportPanel.js
@@ -652,6 +652,14 @@ Ext4.define('MCC.panel.MccImportPanel', {
parsedRows: parsedRows,
panel: this
}
+ },{
+ text: 'Process Missing IDs',
+ action: this.processMissingIds,
+ rowData: {
+ colArray: colArray,
+ parsedRows: parsedRows,
+ panel: this
+ }
}],
columns: columns
});
@@ -663,6 +671,302 @@ Ext4.define('MCC.panel.MccImportPanel', {
}
},
+ processMissingIds: function(e, dt, node, config) {
+ Ext4.Msg.wait('Loading...');
+
+ var idToColony = {};
+ var colonyToId = {};
+ config.rowData.parsedRows.forEach(function(row){
+ idToColony[row.Id] = row.colony;
+
+ if (!colonyToId[row.colony]) {
+ colonyToId[row.colony] = [];
+ }
+
+ colonyToId[row.colony].push(row.Id);
+ });
+
+ var missingIds = []
+ var multi = new LABKEY.MultiRequest();
+ for (var colony in colonyToId) {
+ multi.add(LABKEY.Query.selectRows, {
+ schemaName: 'study',
+ queryName: 'demographics',
+ columns: 'Id,colony,objectid,lsid,calculated_status',
+ filterArray: [
+ LABKEY.Filter.create('colony', colony, LABKEY.Filter.Types.EQUAL),
+ LABKEY.Filter.create('calculated_status', 'Alive', LABKEY.Filter.Types.EQUAL),
+ LABKEY.Filter.create('Id', colonyToId[colony].join(';'), LABKEY.Filter.Types.NOT_IN)
+ ],
+ scope: this,
+ failure: LDK.Utils.getErrorCallback(),
+ success: function (results) {
+ if (results.rows.length) {
+ missingIds = missingIds.concat(results.rows);
+ }
+ }
+ });
+ }
+
+ multi.send(function(){
+ Ext4.Msg.hide();
+ if (missingIds.length) {
+ Ext4.create('Ext.window.Window', {
+ bodyStyle: 'padding: 5px;',
+ width: 600,
+ modal: true,
+ title: 'Reconcile Census with Existing IDs',
+ effectiveDate: config.rowData.panel.IMPORT_DATE,
+ defaults: {
+ labelWidth: 200,
+ width: 575,
+ },
+ items: [{
+ html: 'The following IDs are listed for the indicated colony, but were not in your census. Choose any status updates and hit submit:',
+ border: false,
+ style: 'padding-bottom: 10px;'
+ },{
+ layout: {
+ type: 'table',
+ columns: 4
+ },
+ border: false,
+ defaults: {
+ border: false,
+ bodyStyle: 'padding: 5px'
+ },
+ items: config.rowData.panel.getAnimalRows(missingIds)
+ }],
+ buttons: [{
+ text: 'Update IDs',
+ scope: this,
+ handler: function(btn) {
+ var demographicsUpdates = [];
+ var deathInserts = [];
+ var departureInserts = [];
+ var win = btn.up('window');
+
+ var missingValues = false;
+ win.query('combo[dataIndex="status_code"]').forEach(function(f){
+ if (f.getValue() && f.getValue() !== f.sourceRecord.calculated_status) {
+ var fields = win.query('field[recordIdx=' + f.recordIdx + ']');
+ LDK.Assert.assertEquality('Incorrect number of MccImportPanel fields', 3, fields.length);
+
+ var dateVal = fields[1].getValue();
+ var otherVal = fields[2].getValue();
+ if (!dateVal || !otherVal) {
+ missingValues = true;
+ return false;
+ }
+
+ if (f.getValue() === 'Dead') {
+ deathInserts.push({
+ Id: f.sourceRecord.Id,
+ objectId: null,
+ QCStateLabel: 'Completed',
+ QCState: null,
+ date: dateVal,
+ cause: otherVal
+ });
+ } else if (f.getValue() === 'Shipped') {
+ departureInserts.push({
+ Id: f.sourceRecord.Id,
+ objectId: null,
+ QCStateLabel: 'Completed',
+ QCState: null,
+ date: dateVal,
+ destination: otherVal
+ });
+ } else {
+ // Handle unknown:
+ demographicsUpdates.push({
+ Id: f.sourceRecord.Id,
+ calculated_status: f.getValue(),
+ lsid: f.sourceRecord.lsid,
+ objectid: f.sourceRecord.objectid
+ });
+ }
+ }
+ });
+
+ if (missingValues) {
+ Ext4.Msg.alert('Error', 'One or more fields is missing a value');
+ return;
+ }
+
+ var commands = [];
+ if (demographicsUpdates.length) {
+ commands.push({
+ command: 'update',
+ schemaName: 'study',
+ queryName: 'demographics',
+ rows: demographicsUpdates
+ });
+ }
+
+ if (departureInserts.length) {
+ commands.push({
+ type: 'insert',
+ schemaName: 'study',
+ queryName: 'departure',
+ rows: departureInserts
+ });
+ }
+
+ if (deathInserts.length) {
+ commands.push({
+ command: 'insert',
+ schemaName: 'study',
+ queryName: 'deaths',
+ rows: deathInserts
+ });
+ }
+
+ if (!commands.length) {
+ Ext4.Msg.alert('No updates', 'No changes, nothing to do');
+ btn.up('window').close();
+ }
+ else {
+ Ext4.Msg.wait('Saving rows...');
+ LABKEY.Query.saveRows({
+ commands: commands,
+ scope: this,
+ success: function() {
+ Ext4.Msg.hide();
+ Ext4.Msg.alert('Success', 'Records updated', function(){
+ btn.up('window').close();
+ }, this);
+ },
+ failure: LDK.Utils.getErrorCallback()
+ });
+ }
+ }
+
+ },{
+ text: 'Cancel',
+ handler: function(btn) {
+ btn.up('window').close();
+ }
+ }]
+ }).show();
+ }
+ else {
+ Ext4.Msg.alert('No missing IDs', 'All existing IDs from these colonies were present in this census, nothing to do');
+ }
+ }, this);
+ },
+
+ getAnimalRows: function(missingIds) {
+ var ret = [{
+ xtype: 'displayfield',
+ width: 125,
+ value: 'Animal Id'
+ }, {
+ xtype: 'displayfield',
+ width: 100,
+ value: 'Status'
+ }, {
+ xtype: 'displayfield',
+ width: 100,
+ value: 'Date'
+ },{
+ xtype: 'displayfield',
+ width: 125,
+ value: 'Destination/Cause'
+ }];
+
+ Ext4.Array.forEach(missingIds, function(r, idx){
+ ret = ret.concat([{
+ xtype: 'displayfield',
+ width: 125,
+ value: r.Id + ' / ' + r.colony
+ }, {
+ xtype: 'ldk-simplecombo',
+ storeValues: Ext4.Array.unique([r.calculated_status, 'Alive', 'Dead', 'Shipped', 'Unknown']),
+ recordIdx: idx,
+ dataIndex: 'status_code',
+ forceSelection: true,
+ sourceRecord: r,
+ width: 100,
+ style: 'margin-right: 5px',
+ value: r.calculated_status,
+ listeners: {
+ render: function (f) {
+ if (f.getValue()) {
+ f.fireEvent('change', f, f.getValue());
+ }
+ },
+ change: function (field, val) {
+ var target1 = field.up('panel').down('container[recordIdx=' + field.recordIdx + '][areaType="date"]');
+ target1.removeAll();
+
+ var target2 = field.up('panel').down('container[recordIdx=' + field.recordIdx + '][areaType="other"]');
+ target2.removeAll();
+
+ var effectiveDate = field.up('window').effectiveDate;
+
+ if (val === 'Shipped') {
+ target1.add({
+ xtype: 'datefield',
+ dataIndex: 'date',
+ labelAlign: 'top',
+ recordIdx: field.recordIdx,
+ style: 'margin-right: 5px',
+ value: effectiveDate
+ });
+
+ target2.add({
+ xtype: 'ldk-simplelabkeycombo',
+ dataIndex: 'destination',
+ labelAlign: 'top',
+ recordIdx: field.recordIdx,
+ schemaName: 'ehr_lookups',
+ queryName: 'source',
+ valueField: 'code',
+ displayField: 'code',
+ forceSelection: true,
+ plugins: ['ldk-usereditablecombo']
+ });
+ }
+ else if (val === 'Dead') {
+ target1.add({
+ xtype: 'datefield',
+ dataIndex: 'date',
+ labelAlign: 'top',
+ recordIdx: field.recordIdx,
+ style: 'margin-right: 5px',
+ value: effectiveDate
+ });
+
+ target2.add({
+ xtype: 'ldk-simplelabkeycombo',
+ dataIndex: 'cause',
+ labelAlign: 'top',
+ recordIdx: field.recordIdx,
+ schemaName: 'ehr_lookups',
+ queryName: 'death_cause',
+ valueField: 'value',
+ displayField: 'value',
+ forceSelection: true,
+ plugins: ['ldk-usereditablecombo']
+ });
+ }
+ }
+ }
+ },{
+ xtype: 'container',
+ recordIdx: idx,
+ areaType: 'date'
+ },{
+ xtype: 'container',
+ recordIdx: idx,
+ areaType: 'other'
+ }]);
+ });
+
+ return(ret);
+ },
+
onSubmit: function(e, dt, node, config){
Ext4.Msg.wait('Saving...');
var rawData = config.rowData.parsedRows;
diff --git a/mcc/resources/web/mcc/window/MarkShippedWindow.js b/mcc/resources/web/mcc/window/MarkShippedWindow.js
index 1302f5476..14245b422 100644
--- a/mcc/resources/web/mcc/window/MarkShippedWindow.js
+++ b/mcc/resources/web/mcc/window/MarkShippedWindow.js
@@ -121,6 +121,7 @@ Ext4.define('MCC.window.MarkShippedWindow', {
return;
}
+ var targetFolderId = win.down('#targetFolder').store.findRecord('Path', targetFolder).get('EntityId');
Ext4.Msg.wait('Saving...');
LABKEY.Query.selectRows({
schemaName: 'study',
@@ -140,7 +141,9 @@ Ext4.define('MCC.window.MarkShippedWindow', {
var newId = win.down('#newId').getValue() || row.Id;
var commands = [];
- if (!row['Id/MostRecentDeparture/MostRecentDeparture']) {
+
+ var shouldAddDeparture = !row['Id/MostRecentDeparture/MostRecentDeparture'] || row['Id/MostRecentDeparture/MostRecentDeparture'] !== Ext4.Date.format(row.effectiveDate, 'Y-m-d') || row.Id !== newId;
+ if (shouldAddDeparture) {
commands.push({
command: 'insert',
schemaName: 'study',
@@ -149,6 +152,7 @@ Ext4.define('MCC.window.MarkShippedWindow', {
Id: row.Id,
date: effectiveDate,
destination: centerName,
+ description: row.colony ? 'Original center: ' + row.colony : null,
qcstate: null,
objectId: null,
QCStateLabel: 'Completed'
@@ -156,52 +160,102 @@ Ext4.define('MCC.window.MarkShippedWindow', {
});
}
- commands.push({
- command: 'insert',
- containerPath: targetFolder,
- schemaName: 'study',
- queryName: 'Demographics',
- rows: [{
- Id: newId,
- date: effectiveDate,
- alternateIds: row.Id !== newId ? row.Id : null,
- gender: row.gender,
- species: row.species,
- birth: row.birth,
- death: row.death,
- dam: row.dam,
- sire: row.sire,
- colony: centerName,
- source: row.colony,
- calculated_status: 'Alive',
- skipMccAliasCreation: true,
- QCState: null,
- QCStateLabel: 'Completed',
- objectId: null
- }]
- });
+ // If going to a new LK folder, we're creating a whole new record:
+ if (targetFolderId.toUpperCase() !== LABKEY.Security.currentContainer.id.toUpperCase() || newId !== row.Id) {
+ commands.push({
+ command: 'insert',
+ containerPath: targetFolder,
+ schemaName: 'study',
+ queryName: 'Demographics',
+ rows: [{
+ Id: newId,
+ date: effectiveDate,
+ alternateIds: row.Id !== newId ? row.Id : null,
+ gender: row.gender,
+ species: row.species,
+ birth: row.birth,
+ death: row.death,
+ dam: row.dam,
+ sire: row.sire,
+ colony: centerName,
+ source: row.colony,
+ calculated_status: 'Alive',
+ skipMccAliasCreation: true,
+ QCState: null,
+ QCStateLabel: 'Completed',
+ objectId: null
+ }]
+ });
- commands.push({
- command: 'insert',
- containerPath: targetFolder,
- schemaName: 'mcc',
- queryName: 'animalMapping',
- rows: [{
- subjectname: newId,
- externalAlias: row['Id/mccAlias/externalAlias']
- }]
- });
+ commands.push({
+ command: 'update',
+ containerPath: null, //Use current folder
+ schemaName: 'study',
+ queryName: 'Demographics',
+ rows: [{
+ Id: newId,
+ excludeFromCensus: true
+ }]
+ });
+ }
+ else {
+ // Otherwise update the existing:
+ commands.push({
+ command: 'update',
+ containerPath: targetFolder,
+ schemaName: 'study',
+ queryName: 'Demographics',
+ rows: [{
+ Id: newId,
+ date: effectiveDate,
+ alternateIds: row.Id !== newId ? row.Id : null,
+ gender: row.gender,
+ species: row.species,
+ birth: row.birth,
+ death: row.death,
+ dam: row.dam,
+ sire: row.sire,
+ colony: centerName,
+ source: row.colony,
+ calculated_status: 'Alive',
+ skipMccAliasCreation: true,
+ QCState: null,
+ QCStateLabel: 'Completed',
+ objectId: null
+ }]
+ });
- commands.push({
- command: 'update',
- containerPath: null, //Use current folder
- schemaName: 'study',
- queryName: 'Demographics',
- rows: [{
- Id: newId,
- excludeFromCensus: true
- }]
- });
+ // And also add an arrival record. NOTE: set the date after the departure to get status to update properly
+ var arrivalDate = new Date(effectiveDate).setMinutes(effectiveDate.getMinutes() + 1);
+ commands.push({
+ command: 'insert',
+ containerPath: targetFolder,
+ schemaName: 'study',
+ queryName: 'Arrival',
+ rows: [{
+ Id: newId,
+ date: arrivalDate,
+ source: centerName,
+ QCState: null,
+ QCStateLabel: 'Completed',
+ objectId: null
+ }]
+ });
+ }
+
+ // Do this insert if we're using a new container, or if the animal is being assigned a new ID
+ if (targetFolderId.toUpperCase() !== LABKEY.Security.currentContainer.id.toUpperCase() || newId !== row.Id) {
+ commands.push({
+ command: 'insert',
+ containerPath: targetFolder,
+ schemaName: 'mcc',
+ queryName: 'animalMapping',
+ rows: [{
+ subjectname: newId,
+ externalAlias: row['Id/mccAlias/externalAlias']
+ }]
+ });
+ }
LABKEY.Query.saveRows({
commands: commands,
diff --git a/mcc/test/src/org/labkey/test/tests/mcc/MccTest.java b/mcc/test/src/org/labkey/test/tests/mcc/MccTest.java
index cf1163020..21beaf35d 100644
--- a/mcc/test/src/org/labkey/test/tests/mcc/MccTest.java
+++ b/mcc/test/src/org/labkey/test/tests/mcc/MccTest.java
@@ -16,6 +16,7 @@
package org.labkey.test.tests.mcc;
+import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import org.junit.Before;
@@ -65,6 +66,15 @@ public void testMccModule() throws Exception
testAnimalImportAndTransfer();
}
+ private static final String ANIMAL_DATA_HEADER = "animal ID\tprevious IDs\tsource\t\"DOB\n(MM/DD/YYYY)\"\tsex\tmaternal ID\tpaternal ID\t\"weight(grams)\"\t\"date of weight\n(MM/DD/YY)\"\tU24 status\tavailalble to transfer\tcurrent housing status\tinfant history\tfertility status\tmedical history\n";
+
+ private static final String ANIMAL_DATA1 = "Animal1\t\t\t7/10/2011\t0 - male\tDam1\tSire1\t382.8\t5/19/2021\t0 - not assigned to U24 breeding colony\t0 - not available for transfer\t1 - natal family group\t3 - successful rearing of offspring\t2 - successful offspring produced\t0 - naive animal\n";
+
+
+ private static final String ANIMAL_DATA2 = "Animal2\t\t\t6/3/2015\t1 - female\tDam2\tSire2\t361.2\t1/28/2021\t0 - not assigned to U24 breeding colony\t0 - not available for transfer\t2 - active breeding\t3 - successful rearing of offspring\t2 - successful offspring produced\t0 - naive animal\n";
+
+ private static final String ANIMAL_DATA3 = "Animal3\t\t\t6/4/2015\t1 - female\tDam2\tSire2\t361.2\t1/28/2021\t0 - not assigned to U24 breeding colony\t0 - not available for transfer\t2 - active breeding\t3 - successful rearing of offspring\t2 - successful offspring produced\t0 - naive animal";
+
private void testAnimalImportAndTransfer() throws Exception
{
beginAt(getProjectName() + "/Colonies/SNPRC/project-begin.view");
@@ -72,11 +82,7 @@ private void testAnimalImportAndTransfer() throws Exception
waitForElement(Locator.tagWithText("label", "Paste Data Below:"));
Ext4FieldRef.getForLabel(this, "Center/Colony Name").setValue("SNPRC");
- Ext4FieldRef.getForLabel(this, "Paste Data Below").setValue(
- "animal ID\tprevious IDs\tsource\t\"DOB\n(MM/DD/YYYY)\"\tsex\tmaternal ID\tpaternal ID\t\"weight(grams)\"\t\"date of weight\n(MM/DD/YY)\"\tU24 status\tavailalble to transfer\tcurrent housing status\tinfant history\tfertility status\tmedical history\n" +
- "Animal1\t\t\t7/10/2011\t0 - male\tDam1\tSire1\t382.8\t5/19/2021\t0 - not assigned to U24 breeding colony\t0 - not available for transfer\t1 - natal family group\t3 - successful rearing of offspring\t2 - successful offspring produced\t0 - naive animal\n" +
- "Animal2\t\t\t6/3/2015\t1 - female\tDam2\tSire2\t361.2\t1/28/2021\t0 - not assigned to U24 breeding colony\t0 - not available for transfer\t2 - active breeding\t3 - successful rearing of offspring\t2 - successful offspring produced\t0 - naive animal"
- );
+ Ext4FieldRef.getForLabel(this, "Paste Data Below").setValue(ANIMAL_DATA_HEADER + ANIMAL_DATA1 + ANIMAL_DATA2 + ANIMAL_DATA3);
waitAndClick(Ext4Helper.Locators.ext4Button("Preview"));
waitForElement(Locator.tagWithText("td", "Animal2").withClass("dt-center"));
@@ -138,6 +144,90 @@ private void testAnimalImportAndTransfer() throws Exception
srr.getRows().forEach(row -> {
Assert.assertEquals("Incorrect QCState", "Completed", row.get("QCState/Label"));
});
+
+ // Now try a within-folder transfer:
+ dr = DataRegionTable.DataRegion(getDriver()).withName("Dataset").waitFor();
+ dr.checkCheckbox(0); //Animal2
+ dr.clickHeaderMenu("More Actions", false, "Mark Animal Shipped");
+
+ new Window.WindowFinder(getDriver()).withTitle("Mark ID Shipped").waitFor();
+ Ext4FieldRef.getForLabel(this, "Effective Date").setValue(new SimpleDateFormat("MM/dd/yyyy").format(new Date()));
+ combo = Ext4ComboRef.getForLabel(this, "Destination Center Name");
+ combo.clickTrigger();
+ waitAndClick(Locator.tagContainingText("li", "Other"));
+
+ dialog = new Window.WindowFinder(getDriver()).withTitle("Enter Value").waitFor();
+ dialog.findElement(Locator.tag("input")).sendKeys("TargetColony2");
+ waitAndClick(Ext4Helper.Locators.ext4Button("OK"));
+ sleep(100);
+
+ Ext4ComboRef.getForLabel(this, "Target Folder").setComboByDisplayValue("Other");
+ waitAndClick(Ext4Helper.Locators.ext4Button("Submit"));
+
+ new Window.WindowFinder(getDriver()).withTitle("Success").waitFor();
+ waitAndClickAndWait(Ext4Helper.Locators.ext4Button("OK"));
+
+ dr = DataRegionTable.DataRegion(getDriver()).withName("Dataset").waitFor();
+ Assert.assertEquals("Incorrect ID", "Animal2", dr.getDataAsText(0, "Id"));
+ Assert.assertEquals("Incorrect Alias", mccId, dr.getDataAsText(0, "MCC Alias"));
+ Assert.assertEquals("Incorrect Status", "", dr.getDataAsText(0, "Status"));
+ Assert.assertEquals("Incorrect Status", "Dam2", dr.getDataAsText(0, "Dam"));
+ Assert.assertEquals("Incorrect Status", "Sire2", dr.getDataAsText(0, "Sire"));
+ Assert.assertNull("Incorrect Value", StringUtils.trimToNull(dr.getDataAsText(0, "Exclude From Census?")));
+ Assert.assertEquals("Incorrect Colony", "TargetColony2", dr.getDataAsText(0, "colony"));
+ Assert.assertEquals("Incorrect Colony", "TargetColony", dr.getDataAsText(0, "source"));
+
+ sr = new SelectRowsCommand("study", "departure");
+ sr.setColumns(Arrays.asList("Id", "QCState/Label"));
+ sr.setFilters(Arrays.asList(new Filter("Id", "Animal2")));
+ srr = sr.execute(createDefaultConnection(), getProjectName() + "/Colonies/Other");
+ Assert.assertEquals("Incorrect number of departures", 1, srr.getRowCount().intValue());
+ srr.getRows().forEach(row -> {
+ Assert.assertEquals("Incorrect QCState", "Completed", row.get("QCState/Label"));
+ });
+
+ // Now check status update:
+ populateLookups("SNPRC"); //status is needed for this to work
+ beginAt(getProjectName() + "/Colonies/SNPRC/project-begin.view");
+ waitAndClickAndWait(Locator.tagWithText("a", "Import Excel-Based Data"));
+ waitForElement(Locator.tagWithText("label", "Paste Data Below:"));
+ Ext4FieldRef.getForLabel(this, "Center/Colony Name").setValue("SNPRC");
+
+ Ext4FieldRef.getForLabel(this, "Paste Data Below").setValue(ANIMAL_DATA_HEADER + ANIMAL_DATA1);
+
+ waitAndClick(Ext4Helper.Locators.ext4Button("Preview"));
+ waitForElement(Locator.tagWithText("td", "Animal1").withClass("dt-center"));
+
+ waitAndClick(getButton("Process Missing IDs"));
+ new Window.WindowFinder(getDriver()).withTitle("Reconcile Census with Existing IDs").waitFor();
+
+ String comboQuery = "combo[dataIndex='status_code']";
+ Ext4ComboRef.waitForComponent(this, comboQuery);
+ Ext4ComboRef statusCombo = _ext4Helper.queryOne(comboQuery, Ext4ComboRef.class);
+ statusCombo.setComboByDisplayValue("Dead");
+
+ String comboQuery2 = "combo[dataIndex='cause']";
+ Ext4ComboRef.waitForComponent(this, comboQuery2);
+ Ext4ComboRef causeCombo = _ext4Helper.queryOne(comboQuery2, Ext4ComboRef.class);
+ causeCombo.setComboByDisplayValue("Cause of Death Unknown");
+
+ waitAndClick(Ext4Helper.Locators.ext4Button("Update IDs"));
+ sleep(100);
+ new Window.WindowFinder(getDriver()).withTitle("Success").waitFor();
+ waitAndClick(Ext4Helper.Locators.ext4Button("OK"));
+
+ sr = new SelectRowsCommand("study", "demographics");
+ sr.setColumns(Arrays.asList("Id", "calculated_status"));
+ sr.setFilters(Arrays.asList(new Filter("Id", "Animal3")));
+ srr = sr.execute(createDefaultConnection(), getProjectName() + "/Colonies/SNPRC");
+ Assert.assertEquals("Incorrect status", "Dead", srr.getRows().get(0).get("calculated_status"));
+
+ sr = new SelectRowsCommand("study", "deaths");
+ sr.setColumns(Arrays.asList("Id", "cause"));
+ sr.setFilters(Arrays.asList(new Filter("Id", "Animal3")));
+ srr = sr.execute(createDefaultConnection(), getProjectName() + "/Colonies/SNPRC");
+ Assert.assertEquals("No death record", 1, srr.getRowCount().intValue());
+ Assert.assertEquals("Incorrect cause", "Cause of Death Unknown", srr.getRows().get(0).get("cause"));
}
private static class FormElement
@@ -678,6 +768,8 @@ private void doRequestFormTestWithFailure() throws Exception
assertElementNotPresent(getButton("Save"));
assertElementNotPresent(getButton("Submit"));
assertElementNotPresent(getButton("Approve Request"));
+
+ stopImpersonating();
}
private FormElement getFormElementByName(String name)
@@ -767,11 +859,23 @@ private void doSetup() throws Exception
}
}
+ private void populateLookups(String name)
+ {
+ beginAt(getProjectName() + "/Colonies/" + name + "/project-begin.view");
+ waitAndClickAndWait(Locator.tagWithText("a", "Populate Lookups"));
+ waitAndClick(Ext4Helper.Locators.ext4Button("Populate Lookup Sets"));
+ waitForElement(Locator.tagWithText("div", "Populating lookup_sets..."));
+ waitForElement(Locator.tagWithText("div", "Populate Complete"));
+
+ waitAndClick(Ext4Helper.Locators.ext4Button("Populate All"));
+ waitForElement(Locator.tagWithText("div", "Populate Complete"));
+ }
+
private void testInvalidId()
{
beginAt("/mcc/" + getProjectName() + "/animalRequest.view?requestId=foo");
- assertElementPresent(Locator.tagWithText("div", "There is no request with id: foo"));
+ waitForElement(Locator.tagWithText("div", "There is no request with id: foo"));
}
diff --git a/tcrdb/src/org/labkey/tcrdb/pipeline/CellRangerVDJCellHashingHandler.java b/tcrdb/src/org/labkey/tcrdb/pipeline/CellRangerVDJCellHashingHandler.java
index d43cfbc7d..d4a798c2b 100644
--- a/tcrdb/src/org/labkey/tcrdb/pipeline/CellRangerVDJCellHashingHandler.java
+++ b/tcrdb/src/org/labkey/tcrdb/pipeline/CellRangerVDJCellHashingHandler.java
@@ -204,10 +204,10 @@ private void processVloupeFile(JobContext ctx, File perCellTsv, Readset rs, Reco
parameters.basename = FileUtil.makeLegalName(rs.getName());
parameters.allowableHtoBarcodes = htosPerReadset;
- // If demuxEM used:
- if (parameters.methods.contains(CellHashingService.CALLING_METHOD.demuxem) || parameters.consensusMethods.contains(CellHashingService.CALLING_METHOD.demuxem))
+ // If demuxEM/demuxmix used:
+ if (CellHashingService.CALLING_METHOD.requiresH5(parameters.methods) || CellHashingService.CALLING_METHOD.requiresH5(parameters.consensusMethods))
{
- ctx.getLogger().debug("demuxEM is used, adding H5 file");
+ ctx.getLogger().debug("demuxEM/demuxmix is used, adding H5 file");
if (genomeId == null)
{
genomeId = ctx.getSequenceSupport().getCachedGenomes().iterator().next().getGenomeId();