From 1060e0b08c8ea22b8d69e0da3ec0c5541705c209 Mon Sep 17 00:00:00 2001 From: labkey-susanh Date: Tue, 28 Jul 2026 16:22:50 -0700 Subject: [PATCH 1/8] Add new source derivation action types and add inputEntityType to workflow.task table --- api/src/org/labkey/api/workflow/Action.java | 57 ++++++++++++++++++- api/src/org/labkey/api/workflow/Task.java | 11 ++++ .../labkey/api/workflow/WorkflowService.java | 4 +- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/api/src/org/labkey/api/workflow/Action.java b/api/src/org/labkey/api/workflow/Action.java index c9a5d30c6ec..217a107682b 100644 --- a/api/src/org/labkey/api/workflow/Action.java +++ b/api/src/org/labkey/api/workflow/Action.java @@ -39,6 +39,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; public abstract class Action extends CreatedModified { @@ -295,7 +296,9 @@ else if (_type == WorkflowService.ActionType.AliquotSamples) return messages; } - else if (_type == WorkflowService.ActionType.DeriveSamples || _type == WorkflowService.ActionType.PoolSamples) + else if (_type == WorkflowService.ActionType.DeriveSamples + || _type == WorkflowService.ActionType.PoolSamples + || _type == WorkflowService.ActionType.DeriveSamplesFromSources) { String emptyMessage = prefix + "data about sample types and sample counts per parent is required for action of type " + _type + "."; @@ -377,6 +380,58 @@ else if (_type == WorkflowService.ActionType.RemoveFromStorage || _type == Workf return Collections.emptyList(); } + else if (_type == WorkflowService.ActionType.DeriveSources) + { + String emptyMessage = prefix + "data about sources types and source counts per parent is required for action of type " + _type + "."; + + if (_inputParameters == null) return List.of(emptyMessage); + + // don't allow more than one target source type + if (_inputParameters.isEmpty()) + return List.of(emptyMessage); + else if (_inputParameters.length() > 1) + return List.of(prefix + "only one source type can be specified for action of type " + _type + "."); + + ExperimentService experimentService = ExperimentService.get(); + AtomicReference invalidId = new AtomicReference<>(); + AtomicReference invalidCount = new AtomicReference<>(); + _inputParameters.keys().forEachRemaining(id -> { + try + { + if (experimentService.getDataClass(Long.valueOf(id)) == null) + invalidId.set(id); + } + catch (NumberFormatException e) + { + invalidId.set(id); + } + Object countObj = _inputParameters.get(id); + if (countObj instanceof String countStr) + try + { + if (Integer.parseInt(countStr) < 0) + invalidCount.set(countObj); + } + catch (NumberFormatException e) + { + invalidCount.set(countObj); + } + else if (countObj instanceof Integer count) + { + if (count < 0) + invalidCount.set(countObj); + } + else + invalidCount.set(countObj); + }); + List messages = new ArrayList<>(); + if (invalidId.get() != null) + messages.add(prefix + "invalid source type ID " + invalidId + "."); + if (invalidCount.get() != null) + messages.add(prefix + "invalid source count value " + invalidCount + "."); + + return messages; + } else { if (_inputParameters != null && !_inputParameters.isEmpty()) diff --git a/api/src/org/labkey/api/workflow/Task.java b/api/src/org/labkey/api/workflow/Task.java index 4571e833701..130f7ecfda8 100644 --- a/api/src/org/labkey/api/workflow/Task.java +++ b/api/src/org/labkey/api/workflow/Task.java @@ -43,6 +43,7 @@ public abstract class Task extends CreatedModified implements Comparable protected String _description; protected String _entityFilter; + protected String _inputEntityType; protected Integer _status; protected Date _startDate; protected Date _endDate; @@ -93,6 +94,16 @@ public void setEntityFilter(String entityFilter) _entityFilter = entityFilter; } + public String getInputEntityType() + { + return _inputEntityType; + } + + public void setInputEntityType(String inputEntityType) + { + _inputEntityType = inputEntityType; + } + @JsonProperty("assignee") public JSONObject getAssigneeJSON() { diff --git a/api/src/org/labkey/api/workflow/WorkflowService.java b/api/src/org/labkey/api/workflow/WorkflowService.java index 47f79911b43..313af4c0651 100644 --- a/api/src/org/labkey/api/workflow/WorkflowService.java +++ b/api/src/org/labkey/api/workflow/WorkflowService.java @@ -45,7 +45,9 @@ enum ActionType CheckOut("input parameters", "Checked out samples"), CheckIn("input parameters", "Checked in samples"), RemoveFromStorage("sample status value", "Removed samples from storage"), - UpdateSampleStatus("sample status value", "Updated sample status"); + UpdateSampleStatus("sample status value", "Updated sample status"), + DeriveSamplesFromSources("derivation source type parameters", "Derived samples from sources"), + DeriveSources("derivation source type parameters", "Derives sources"); private final String _inputDescription; private final String _auditMessage; From bc0ec968058ce8568a3be32fe6a11d1f292c98cd Mon Sep 17 00:00:00 2001 From: labkey-susanh Date: Wed, 29 Jul 2026 09:46:38 -0700 Subject: [PATCH 2/8] Update data iterators to add sources to jobs based on actions --- .../labkey/api/workflow/WorkflowService.java | 3 +++ .../api/ExpDataClassDataTableImpl.java | 21 ++++++++++++++++++- .../api/SampleTypeUpdateServiceDI.java | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/api/src/org/labkey/api/workflow/WorkflowService.java b/api/src/org/labkey/api/workflow/WorkflowService.java index 313af4c0651..b626e2b1cbe 100644 --- a/api/src/org/labkey/api/workflow/WorkflowService.java +++ b/api/src/org/labkey/api/workflow/WorkflowService.java @@ -86,9 +86,12 @@ static WorkflowService get() void onActionComplete(@NotNull Container container, @NotNull User user, @NotNull Long actionId, @Nullable String userAuditComment); void onActionComplete(@NotNull Container container, @NotNull User user, @NotNull Long taskId, @NotNull ActionType actionType); boolean actionWillAddSamples(Long actionId); + boolean actionWillAddSources(Long actionId); DataIteratorBuilder getSampleCreationDataIteratorBuilder(DataIteratorBuilder data, Container container, User user); + DataIteratorBuilder getSourceCreationDataIteratorBuilder(DataIteratorBuilder data, Container container, User user); + DataIteratorBuilder getActionAuditDataIteratorBuilder(DataIteratorBuilder data, Container container, User user); @Nullable diff --git a/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java b/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java index 8ac51e4d2f5..8ee4df7a9ed 100644 --- a/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java +++ b/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java @@ -124,6 +124,7 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.view.UnauthorizedException; import org.labkey.api.view.ViewContext; +import org.labkey.api.workflow.WorkflowService; import org.labkey.data.xml.TableType; import org.labkey.experiment.ExpDataIterators; import org.labkey.experiment.ExpDataIterators.AliasDataIteratorBuilder; @@ -942,8 +943,26 @@ public DataIteratorBuilder persistRows(DataIteratorBuilder data, DataIteratorCon }, DbScope.CommitTaskOption.POSTCOMMIT)); + DataIteratorBuilder builder = LoggingDataIterator.wrap(step0); - return LoggingDataIterator.wrap(new AliasDataIteratorBuilder(builder, getUserSchema().getContainer(), getUserSchema().getUser(), ExperimentService.get().getTinfoDataAliasMap(), _dataClass, false)); + UserSchema userSchema = getUserSchema(); + builder = LoggingDataIterator.wrap(new AliasDataIteratorBuilder(builder, userSchema.getContainer(), userSchema.getUser(), ExperimentService.get().getTinfoDataAliasMap(), _dataClass, false)); + WorkflowService workService = WorkflowService.get(); + if (workService != null) + { + if (context.getConfigParameter(WorkflowService.WorkflowConfigs.ActionId) != null) + { + Long actionId = (Long) context.getConfigParameter(WorkflowService.WorkflowConfigs.ActionId); + + if (workService.actionWillAddSamples(actionId)) + builder = workService.getSampleCreationDataIteratorBuilder(builder, userSchema.getContainer(), userSchema.getUser()); + if (workService.actionWillAddSources(actionId)) + builder = workService.getSourceCreationDataIteratorBuilder(builder, userSchema.getContainer(), userSchema.getUser()); + + builder = workService.getActionAuditDataIteratorBuilder(builder, userSchema.getContainer(), userSchema.getUser()); + } + } + return builder; } catch (IOException e) { diff --git a/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java b/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java index bf0f993ea08..4e8962a9219 100644 --- a/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java +++ b/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java @@ -429,7 +429,7 @@ public DataIteratorBuilder createImportDIB(User user, Container container, DataI { Long actionId = (Long) context.getConfigParameter(WorkflowService.WorkflowConfigs.ActionId); - if (WorkflowService.get().actionWillAddSamples(actionId)) + if (workService.actionWillAddSamples(actionId)) { dib = workService.getSampleCreationDataIteratorBuilder(dib, userSchema.getContainer(), userSchema.getUser()); } From 9640846a245fd8c1b3b93b4928050df1f90948a1 Mon Sep 17 00:00:00 2001 From: labkey-susanh Date: Thu, 30 Jul 2026 08:09:35 -0700 Subject: [PATCH 3/8] Add inputEntityType to audit log map --- api/src/org/labkey/api/workflow/Task.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/org/labkey/api/workflow/Task.java b/api/src/org/labkey/api/workflow/Task.java index 130f7ecfda8..9e53148cfb8 100644 --- a/api/src/org/labkey/api/workflow/Task.java +++ b/api/src/org/labkey/api/workflow/Task.java @@ -289,6 +289,8 @@ public Map toAuditDetailMap() map.put("dueDate", getDueDate()); if (getEntityId() != null) map.put("entityId", getEntityId().toString()); + if (getInputEntityType() != null) + map.put("inputEntityType", getInputEntityType()); map.put("ordinal", getOrdinal()); int actionIndex = 1; for (Action action : getActions()) From 4a40f0939020f2daaab32a540cae38a9b8451df3 Mon Sep 17 00:00:00 2001 From: labkey-susanh Date: Mon, 3 Aug 2026 14:59:10 -0700 Subject: [PATCH 4/8] No need to check for adding samples when deriving data class objects --- .../org/labkey/experiment/api/ExpDataClassDataTableImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java b/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java index 8ee4df7a9ed..37f76dc027a 100644 --- a/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java +++ b/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java @@ -954,8 +954,6 @@ public DataIteratorBuilder persistRows(DataIteratorBuilder data, DataIteratorCon { Long actionId = (Long) context.getConfigParameter(WorkflowService.WorkflowConfigs.ActionId); - if (workService.actionWillAddSamples(actionId)) - builder = workService.getSampleCreationDataIteratorBuilder(builder, userSchema.getContainer(), userSchema.getUser()); if (workService.actionWillAddSources(actionId)) builder = workService.getSourceCreationDataIteratorBuilder(builder, userSchema.getContainer(), userSchema.getUser()); From e4991598ee1c393f6fc5ee9016c7df664ec06b4c Mon Sep 17 00:00:00 2001 From: labkey-susanh Date: Tue, 4 Aug 2026 13:16:25 -0700 Subject: [PATCH 5/8] Add validation for actions not matching task inputs --- api/src/org/labkey/api/workflow/Action.java | 11 +++++-- api/src/org/labkey/api/workflow/Task.java | 6 ++-- .../labkey/api/workflow/WorkflowService.java | 33 +++++++++++-------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/api/src/org/labkey/api/workflow/Action.java b/api/src/org/labkey/api/workflow/Action.java index 217a107682b..501cef57309 100644 --- a/api/src/org/labkey/api/workflow/Action.java +++ b/api/src/org/labkey/api/workflow/Action.java @@ -361,9 +361,14 @@ else if (countObj instanceof Integer count) if (hasAnySampleStatusKey()) { - String statusMessage = validateStatus(container, prefix, true); + if (_type == WorkflowService.ActionType.DeriveSamplesFromSources) + messages.add(prefix + "data about updating parent status not allowed for action of type " + _type + "."); + else + { + String statusMessage = validateStatus(container, prefix, true); - if (statusMessage != null) messages.add(statusMessage); + if (statusMessage != null) messages.add(statusMessage); + } } return messages; @@ -382,7 +387,7 @@ else if (_type == WorkflowService.ActionType.RemoveFromStorage || _type == Workf } else if (_type == WorkflowService.ActionType.DeriveSources) { - String emptyMessage = prefix + "data about sources types and source counts per parent is required for action of type " + _type + "."; + String emptyMessage = prefix + "data about source types and source counts per parent is required for action of type " + _type + "."; if (_inputParameters == null) return List.of(emptyMessage); diff --git a/api/src/org/labkey/api/workflow/Task.java b/api/src/org/labkey/api/workflow/Task.java index 9e53148cfb8..2316b89bcd9 100644 --- a/api/src/org/labkey/api/workflow/Task.java +++ b/api/src/org/labkey/api/workflow/Task.java @@ -43,7 +43,7 @@ public abstract class Task extends CreatedModified implements Comparable protected String _description; protected String _entityFilter; - protected String _inputEntityType; + protected WorkEntity.EntityType _inputEntityType; protected Integer _status; protected Date _startDate; protected Date _endDate; @@ -94,12 +94,12 @@ public void setEntityFilter(String entityFilter) _entityFilter = entityFilter; } - public String getInputEntityType() + public WorkEntity.EntityType getInputEntityType() { return _inputEntityType; } - public void setInputEntityType(String inputEntityType) + public void setInputEntityType(WorkEntity.EntityType inputEntityType) { _inputEntityType = inputEntityType; } diff --git a/api/src/org/labkey/api/workflow/WorkflowService.java b/api/src/org/labkey/api/workflow/WorkflowService.java index b626e2b1cbe..d51bf41b381 100644 --- a/api/src/org/labkey/api/workflow/WorkflowService.java +++ b/api/src/org/labkey/api/workflow/WorkflowService.java @@ -36,26 +36,28 @@ enum WorkflowConfigs enum ActionType { - AssayImport("assay types", "Imported assay data"), - DeriveSamples("derivation sample type parameters", "Derived samples"), - AliquotSamples("aliquot sample type parameters", "Aliquot samples"), - PoolSamples("pooling sample type parameters", "Pooled samples"), - AddToStorage("input parameters", "Added samples to storage"), - MoveInStorage("input parameters", "Moved samples in storage"), - CheckOut("input parameters", "Checked out samples"), - CheckIn("input parameters", "Checked in samples"), - RemoveFromStorage("sample status value", "Removed samples from storage"), - UpdateSampleStatus("sample status value", "Updated sample status"), - DeriveSamplesFromSources("derivation source type parameters", "Derived samples from sources"), - DeriveSources("derivation source type parameters", "Derives sources"); + AssayImport("assay types", "Imported assay data", WorkEntity.EntityType.Sample), + DeriveSamples("derivation sample type parameters", "Derived samples", WorkEntity.EntityType.Sample), + AliquotSamples("aliquot sample type parameters", "Aliquot samples", WorkEntity.EntityType.Sample), + PoolSamples("pooling sample type parameters", "Pooled samples", WorkEntity.EntityType.Sample), + AddToStorage("input parameters", "Added samples to storage", WorkEntity.EntityType.Sample), + MoveInStorage("input parameters", "Moved samples in storage", WorkEntity.EntityType.Sample), + CheckOut("input parameters", "Checked out samples", WorkEntity.EntityType.Sample), + CheckIn("input parameters", "Checked in samples", WorkEntity.EntityType.Sample), + RemoveFromStorage("sample status value", "Removed samples from storage", WorkEntity.EntityType.Sample), + UpdateSampleStatus("sample status value", "Updated sample status", WorkEntity.EntityType.Sample), + DeriveSamplesFromSources("derivation source type parameters", "Derived samples from sources", WorkEntity.EntityType.Source), + DeriveSources("derivation source type parameters", "Derived sources", WorkEntity.EntityType.Source); private final String _inputDescription; private final String _auditMessage; + private final WorkEntity.EntityType _inputEntityType; - ActionType(String inputDescription, String auditMessage) + ActionType(String inputDescription, String auditMessage, WorkEntity.EntityType inputEntityType) { _inputDescription = inputDescription; _auditMessage = auditMessage; + _inputEntityType = inputEntityType; } public String getInputDescription() @@ -67,6 +69,11 @@ public String getAuditMessage() { return _auditMessage; } + + public WorkEntity.EntityType getInputEntityType() + { + return _inputEntityType; + } } static void setInstance(WorkflowService impl) From bb85a2d6e26d224b26c87365d81df2427576a19d Mon Sep 17 00:00:00 2001 From: labkey-susanh Date: Tue, 4 Aug 2026 15:00:01 -0700 Subject: [PATCH 6/8] Various bits of cleanup --- api/src/org/labkey/api/workflow/Action.java | 78 ++++++++++--------- .../controllers/exp/ExperimentController.java | 26 ++++--- 2 files changed, 58 insertions(+), 46 deletions(-) diff --git a/api/src/org/labkey/api/workflow/Action.java b/api/src/org/labkey/api/workflow/Action.java index 501cef57309..99ccab0a87a 100644 --- a/api/src/org/labkey/api/workflow/Action.java +++ b/api/src/org/labkey/api/workflow/Action.java @@ -39,7 +39,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; public abstract class Action extends CreatedModified { @@ -391,49 +390,58 @@ else if (_type == WorkflowService.ActionType.DeriveSources) if (_inputParameters == null) return List.of(emptyMessage); - // don't allow more than one target source type - if (_inputParameters.isEmpty()) + // We can't just check _inputParameters size because it may include sample status keys, so we extract the + // source type IDs and validate against those. + List sourceTypeIds = new ArrayList<>(); + _inputParameters.keys().forEachRemaining(id -> { + if (isSampleStatusKey(id)) return; + sourceTypeIds.add(id); + }); + + if (sourceTypeIds.isEmpty()) return List.of(emptyMessage); - else if (_inputParameters.length() > 1) + + // don't allow more than one target source type + if (sourceTypeIds.size() > 1) return List.of(prefix + "only one source type can be specified for action of type " + _type + "."); - ExperimentService experimentService = ExperimentService.get(); - AtomicReference invalidId = new AtomicReference<>(); - AtomicReference invalidCount = new AtomicReference<>(); - _inputParameters.keys().forEachRemaining(id -> { + List messages = new ArrayList<>(); + String sourceTypeId = sourceTypeIds.get(0); + boolean invalidId; + try + { + invalidId = ExperimentService.get().getDataClass(container, Long.parseLong(sourceTypeId), true) == null; + } + catch (NumberFormatException e) + { + invalidId = true; + } + if (invalidId) + messages.add(prefix + "invalid source type ID " + sourceTypeId + "."); + + Object countObj = _inputParameters.get(sourceTypeId); + boolean invalidCount; + if (countObj instanceof String countStr) + { try { - if (experimentService.getDataClass(Long.valueOf(id)) == null) - invalidId.set(id); + invalidCount = Integer.parseInt(countStr) < 0; } catch (NumberFormatException e) { - invalidId.set(id); - } - Object countObj = _inputParameters.get(id); - if (countObj instanceof String countStr) - try - { - if (Integer.parseInt(countStr) < 0) - invalidCount.set(countObj); - } - catch (NumberFormatException e) - { - invalidCount.set(countObj); - } - else if (countObj instanceof Integer count) - { - if (count < 0) - invalidCount.set(countObj); + invalidCount = true; } - else - invalidCount.set(countObj); - }); - List messages = new ArrayList<>(); - if (invalidId.get() != null) - messages.add(prefix + "invalid source type ID " + invalidId + "."); - if (invalidCount.get() != null) - messages.add(prefix + "invalid source count value " + invalidCount + "."); + } + else if (countObj instanceof Integer count) + invalidCount = count < 0; + else + invalidCount = true; + + if (invalidCount) + messages.add(prefix + "invalid source count value " + countObj + "."); + + if (hasAnySampleStatusKey()) + messages.add(prefix + "data about updating parent status not allowed for action of type " + _type + "."); return messages; } diff --git a/experiment/src/org/labkey/experiment/controllers/exp/ExperimentController.java b/experiment/src/org/labkey/experiment/controllers/exp/ExperimentController.java index 93211baf5d7..bb8d487ee41 100644 --- a/experiment/src/org/labkey/experiment/controllers/exp/ExperimentController.java +++ b/experiment/src/org/labkey/experiment/controllers/exp/ExperimentController.java @@ -4426,17 +4426,6 @@ protected int importData( tInfo = ExperimentService.get().createMaterialTable(new SamplesSchema(getUser(), getContainer()), ContainerFilter.current(this), null); updateService = tInfo.getUpdateService(); } - if (WorkflowService.get() != null) - { - try - { - WorkflowService.get().populateConfigParams(getViewContext().getRequest(), _context.getConfigParameters()); - } - catch (ValidationException e) - { - errors.addRowError(e); - } - } int count = importData(dl, tInfo, updateService, _context, auditEvent, getUser(), getContainer()); @@ -4551,6 +4540,21 @@ protected Set getLineageImportAliases() throws IOException protected void initContext(DataLoader dl, BatchValidationException errors, @Nullable AuditBehaviorType auditBehaviorType, @Nullable String auditUserComment) { _context = createDataIteratorContext(_insertOption, getOptionParamsMap(), getLookupResolutionType(), auditBehaviorType, auditUserComment, errors, null, getContainer()); + + // Both samples and data classes can be created via a workflow job action, so the action and job ids need to + // be available to the update service for either type. The background import path populates these separately + // via AbstractQueryImportAction.getImportContextBuilder(). + if (WorkflowService.get() != null) + { + try + { + WorkflowService.get().populateConfigParams(getViewContext().getRequest(), _context.getConfigParameters()); + } + catch (ValidationException e) + { + errors.addRowError(e); + } + } } @Override From 3beb913c9db2c2c52fc161e56847164c589a050e Mon Sep 17 00:00:00 2001 From: labkey-susanh Date: Wed, 5 Aug 2026 08:47:26 -0700 Subject: [PATCH 7/8] Check insert option is not an update before adding workflow data iterators for samples and sources --- .../org/labkey/experiment/api/ExpDataClassDataTableImpl.java | 2 +- .../org/labkey/experiment/api/SampleTypeUpdateServiceDI.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java b/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java index 37f76dc027a..df04f6fc6f5 100644 --- a/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java +++ b/experiment/src/org/labkey/experiment/api/ExpDataClassDataTableImpl.java @@ -948,7 +948,7 @@ public DataIteratorBuilder persistRows(DataIteratorBuilder data, DataIteratorCon UserSchema userSchema = getUserSchema(); builder = LoggingDataIterator.wrap(new AliasDataIteratorBuilder(builder, userSchema.getContainer(), userSchema.getUser(), ExperimentService.get().getTinfoDataAliasMap(), _dataClass, false)); WorkflowService workService = WorkflowService.get(); - if (workService != null) + if (workService != null && !context.getInsertOption().allowUpdate) { if (context.getConfigParameter(WorkflowService.WorkflowConfigs.ActionId) != null) { diff --git a/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java b/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java index 4e8962a9219..331cdbcb453 100644 --- a/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java +++ b/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java @@ -423,7 +423,7 @@ public DataIteratorBuilder createImportDIB(User user, Container container, DataI if (sampleType.getAutoLinkTargetContainer() != null && StudyPublishService.get() != null && !context.getInsertOption().updateOnly/* TODO support link to study on update? */) dib = LoggingDataIterator.wrap(new ExpDataIterators.AutoLinkToStudyDataIteratorBuilder(dib, getSchema(), userSchema.getContainer(), userSchema.getUser(), sampleType)); WorkflowService workService = WorkflowService.get(); - if (workService != null) + if (workService != null && !context.getInsertOption().allowUpdate) { if (context.getConfigParameter(WorkflowService.WorkflowConfigs.ActionId) != null) { From 65e61fb7f375f003aef5e0aa97b9bafe528a3fea Mon Sep 17 00:00:00 2001 From: XingY Date: Mon, 10 Aug 2026 16:33:55 -0700 Subject: [PATCH 8/8] Fix update sample status action audits --- .../org/labkey/experiment/api/SampleTypeUpdateServiceDI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java b/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java index 331cdbcb453..19d7c6e1a9e 100644 --- a/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java +++ b/experiment/src/org/labkey/experiment/api/SampleTypeUpdateServiceDI.java @@ -423,13 +423,13 @@ public DataIteratorBuilder createImportDIB(User user, Container container, DataI if (sampleType.getAutoLinkTargetContainer() != null && StudyPublishService.get() != null && !context.getInsertOption().updateOnly/* TODO support link to study on update? */) dib = LoggingDataIterator.wrap(new ExpDataIterators.AutoLinkToStudyDataIteratorBuilder(dib, getSchema(), userSchema.getContainer(), userSchema.getUser(), sampleType)); WorkflowService workService = WorkflowService.get(); - if (workService != null && !context.getInsertOption().allowUpdate) + if (workService != null) { if (context.getConfigParameter(WorkflowService.WorkflowConfigs.ActionId) != null) { Long actionId = (Long) context.getConfigParameter(WorkflowService.WorkflowConfigs.ActionId); - if (workService.actionWillAddSamples(actionId)) + if (workService.actionWillAddSamples(actionId) && !context.getInsertOption().allowUpdate) { dib = workService.getSampleCreationDataIteratorBuilder(dib, userSchema.getContainer(), userSchema.getUser()); }