By default, new timepoint rows will be created in the study during the insert or update of any dataset or
+ specimen rows which have a new, undefined timepoint. If, instead you would like
+ for the operation to fail when it encounters a visit that is not already defined in the study, check the box
+ below.
+
allVisits = getVisits(Visit.Order.DISPLAY);
%>
+
| View study schedule |
@@ -79,6 +81,19 @@
<%= link("Create New Visit", CreateVisitAction.class)%> |
+
+
+
+ By default, new visit rows will be created in the study during the insert or update of any dataset or
+ specimen rows which have a new, undefined visit. If, instead you would like
+ for the operation to fail when it encounters a visit that is not already defined in the study, check the box
+ below.
+
+
+ <%= button("Update").submit(true) %>
+
+
<%
if (allVisits.size() > 0)
diff --git a/study/src/org/labkey/study/visitmanager/AbsoluteDateVisitManager.java b/study/src/org/labkey/study/visitmanager/AbsoluteDateVisitManager.java
index 2dd228bae46..88ea5a307e1 100644
--- a/study/src/org/labkey/study/visitmanager/AbsoluteDateVisitManager.java
+++ b/study/src/org/labkey/study/visitmanager/AbsoluteDateVisitManager.java
@@ -17,11 +17,13 @@
package org.labkey.study.visitmanager;
import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.labkey.api.data.ColumnInfo;
import org.labkey.api.data.SQLFragment;
import org.labkey.api.data.TableInfo;
import org.labkey.api.query.FilteredTable;
+import org.labkey.api.query.ValidationException;
import org.labkey.api.security.User;
import org.labkey.api.study.CohortFilter;
import org.labkey.api.study.DataspaceContainerFilter;
@@ -147,8 +149,9 @@ protected void updateParticipantVisitTable(@Nullable User user, @Nullable Logger
}
@Override
- protected void updateVisitTable(User user, @Nullable Logger logger)
+ protected @NotNull ValidationException updateVisitTable(User user, @Nullable Logger logger, boolean failForUndefinedVisits)
{
// no-op
+ return new ValidationException();
}
}
diff --git a/study/src/org/labkey/study/visitmanager/RelativeDateVisitManager.java b/study/src/org/labkey/study/visitmanager/RelativeDateVisitManager.java
index 344b9105403..7de09e8b1a3 100644
--- a/study/src/org/labkey/study/visitmanager/RelativeDateVisitManager.java
+++ b/study/src/org/labkey/study/visitmanager/RelativeDateVisitManager.java
@@ -17,6 +17,7 @@
package org.labkey.study.visitmanager;
import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.labkey.api.data.ColumnInfo;
import org.labkey.api.data.Container;
@@ -29,6 +30,7 @@
import org.labkey.api.data.TableInfo;
import org.labkey.api.query.FieldKey;
import org.labkey.api.query.FilteredTable;
+import org.labkey.api.query.ValidationException;
import org.labkey.api.security.User;
import org.labkey.api.study.CohortFilter;
import org.labkey.api.study.Study;
@@ -299,7 +301,7 @@ private void _updateVisitRowId()
/** Make sure there is a Visit for each row in StudyData otherwise rows will be orphaned */
@Override
- protected void updateVisitTable(final User user, @Nullable Logger logger)
+ protected @NotNull ValidationException updateVisitTable(final User user, @Nullable Logger logger, boolean failForUndefinedVisits)
{
DbSchema schema = StudySchema.getInstance().getSchema();
TableInfo tableParticipantVisit = StudySchema.getInstance().getTableInfoParticipantVisit();
@@ -317,13 +319,15 @@ protected void updateVisitTable(final User user, @Nullable Logger logger)
daysToEnsure.add(seqNum);
});
- StudyManager.getInstance().ensureVisits(getStudy(), user, daysToEnsure, null);
+ ValidationException errors = StudyManager.getInstance().ensureVisits(getStudy(), user, daysToEnsure, null, failForUndefinedVisits);
if (daysToEnsure.size() > 0)
_updateVisitRowId();
+
+ return errors;
}
- public void recomputeDates(Date oldStartDate, User user)
+ public @Nullable ValidationException recomputeDates(Date oldStartDate, User user)
{
if (null != oldStartDate)
{
@@ -344,9 +348,10 @@ public void recomputeDates(Date oldStartDate, User user)
executor.execute("DELETE FROM " + tableVisit + " WHERE Container=?", c);
//Now recompute everything
- updateParticipantVisits(user, getStudy().getDatasets());
+ return updateParticipantVisits(user, getStudy().getDatasets());
}
}
+ return null;
}
// Return sql for fetching all datasets and their visit sequence numbers, given a container
diff --git a/study/src/org/labkey/study/visitmanager/SequenceVisitManager.java b/study/src/org/labkey/study/visitmanager/SequenceVisitManager.java
index 25f6f118e4e..7250a46e8b5 100644
--- a/study/src/org/labkey/study/visitmanager/SequenceVisitManager.java
+++ b/study/src/org/labkey/study/visitmanager/SequenceVisitManager.java
@@ -18,6 +18,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.labkey.api.data.ColumnInfo;
import org.labkey.api.data.Container;
@@ -30,6 +31,7 @@
import org.labkey.api.data.dialect.SqlDialect;
import org.labkey.api.query.FieldKey;
import org.labkey.api.query.FilteredTable;
+import org.labkey.api.query.ValidationException;
import org.labkey.api.security.User;
import org.labkey.api.study.CohortFilter;
import org.labkey.api.study.Study;
@@ -37,7 +39,6 @@
import org.labkey.api.study.Visit;
import org.labkey.api.study.model.ParticipantGroup;
import org.labkey.api.util.DateUtil;
-import org.labkey.api.util.GUID;
import org.labkey.study.StudySchema;
import org.labkey.study.StudyUnionTableInfo;
import org.labkey.study.model.DatasetDefinition;
@@ -495,10 +496,11 @@ private void _updateVisitRowId(boolean updateAll, @Nullable Logger logger)
/** Make sure there is a Visit for each row in StudyData otherwise rows will be orphaned */
@Override
- protected void updateVisitTable(User user, @Nullable Logger logger)
+ protected @NotNull ValidationException updateVisitTable(User user, @Nullable Logger logger, boolean failForUndefinedVisits)
{
DbSchema schema = StudySchema.getInstance().getSchema();
TableInfo tableParticipantVisit = StudySchema.getInstance().getTableInfoParticipantVisit();
+ ValidationException errors = new ValidationException();
SQLFragment sql = new SQLFragment("SELECT DISTINCT SequenceNum\n" +
"FROM " + tableParticipantVisit + "\n"+
@@ -513,9 +515,10 @@ protected void updateVisitTable(User user, @Nullable Logger logger)
if (sequenceNums.size() > 0)
{
info(logger, "Ensure visits for " + sequenceNums.size() + " distinct sequence numbers");
- StudyManager.getInstance().ensureVisits(getStudy(), user, sequenceNums, null);
+ errors = StudyManager.getInstance().ensureVisits(getStudy(), user, sequenceNums, null, failForUndefinedVisits);
_updateVisitRowId(true, logger);
}
+ return errors;
}
diff --git a/study/src/org/labkey/study/visitmanager/VisitManager.java b/study/src/org/labkey/study/visitmanager/VisitManager.java
index 3649071ed9f..893a2468b40 100644
--- a/study/src/org/labkey/study/visitmanager/VisitManager.java
+++ b/study/src/org/labkey/study/visitmanager/VisitManager.java
@@ -40,6 +40,7 @@
import org.labkey.api.data.TableSelector;
import org.labkey.api.exceptions.TableNotFoundException;
import org.labkey.api.query.FieldKey;
+import org.labkey.api.query.ValidationException;
import org.labkey.api.search.SearchService;
import org.labkey.api.security.User;
import org.labkey.api.specimen.SpecimenSchema;
@@ -97,27 +98,25 @@ protected VisitManager(StudyImpl study)
* @param user the current user
* @param changedDatasets the datasets that may have one or more rows modified
*/
- public void updateParticipantVisits(User user, @NotNull Collection changedDatasets)
+ public ValidationException updateParticipantVisits(User user, @NotNull Collection changedDatasets)
{
- updateParticipantVisits(user, changedDatasets, null, null, true, null);
+ return updateParticipantVisits(user, changedDatasets, null, null, true, _study.isFailForUndefinedTimepoints(), null);
}
- public void updateParticipantVisits(User user, @NotNull Collection changedDatasets, @Nullable Logger logger)
+ public ValidationException updateParticipantVisitsWithCohortUpdate(User user, boolean failForUndefinedVisits, @Nullable Logger logger)
{
- updateParticipantVisits(user, changedDatasets, null, null, true, logger);
+ return updateParticipantVisits(user, Collections.emptyList(), null, null, true, failForUndefinedVisits, logger);
}
- public void updateParticipantVisitsWithCohortUpdate(User user, @Nullable Logger logger)
- {
- updateParticipantVisits(user, Collections.emptyList(), null, null, true, true, logger);
- }
-
- public void updateParticipantVisits(User user, @NotNull Collection changedDatasets, @Nullable Set potentiallyAddedParticipants,
- @Nullable Set potentiallyDeletedParticipants, boolean participantVisitResyncRequired,
+ public ValidationException updateParticipantVisits(User user, @NotNull Collection changedDatasets,
+ @Nullable Set potentiallyAddedParticipants,
+ @Nullable Set potentiallyDeletedParticipants,
+ boolean participantVisitResyncRequired,
+ boolean failForUndefinedVisits,
@Nullable Logger logger)
{
- updateParticipantVisits(user, changedDatasets, potentiallyAddedParticipants, potentiallyDeletedParticipants,
- participantVisitResyncRequired, false, logger);
+ return _updateParticipantVisits(user, changedDatasets, potentiallyAddedParticipants, potentiallyDeletedParticipants,
+ participantVisitResyncRequired, failForUndefinedVisits, logger);
}
protected void info(@Nullable Logger logger, String message)
@@ -131,16 +130,19 @@ protected void info(@Nullable Logger logger, String message)
* @param user the current user
* @param changedDatasets the datasets that may have one or more rows modified
* @param potentiallyAddedParticipants optionally, the specific participants that may have been added to the study.
- * If null, all of the changedDatasets and specimens will be checked to see if they contain new participants
+ * If null, all the changedDatasets and specimens will be checked to see if they contain new participants
* @param potentiallyDeletedParticipants optionally, the specific participants that may have been removed from the
* study. If null, all participants will be checked to see if they are still in the study.
* @param participantVisitResyncRequired If true, will force an update of the ParticipantVisit mapping for this study
- * @param forceUpdateCohorts If true, forces updateParticipantCohorts() (specimen import case)
+ * @param failForUndefinedVisits If true, will return an error if visits do not currently exist in the study
* @param logger Log4j logger to use for detailed performance information
*/
- public void updateParticipantVisits(User user, @NotNull Collection changedDatasets, @Nullable Set potentiallyAddedParticipants,
- @Nullable Set potentiallyDeletedParticipants, boolean participantVisitResyncRequired,
- boolean forceUpdateCohorts, @Nullable Logger logger)
+ private ValidationException _updateParticipantVisits(User user, @NotNull Collection changedDatasets,
+ @Nullable Set potentiallyAddedParticipants,
+ @Nullable Set potentiallyDeletedParticipants,
+ boolean participantVisitResyncRequired,
+ boolean failForUndefinedVisits,
+ @Nullable Logger logger)
{
info(logger, "Updating participants");
updateParticipants(changedDatasets, potentiallyAddedParticipants, potentiallyDeletedParticipants);
@@ -163,22 +165,21 @@ public void updateParticipantVisits(User user, @NotNull Collection