Skip to content

Commit 68b5f1b

Browse files
committed
RSDEV-280: Return the list of Subsamples when cannot delete a Sample
1 parent c894832 commit 68b5f1b

File tree

12 files changed

+72
-54
lines changed

12 files changed

+72
-54
lines changed

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3037,7 +3037,7 @@
30373037
<jstl.version>1.1.2</jstl.version>
30383038
<lucene.version>5.5.5</lucene.version>
30393039
<netty.version>4.1.63.Final</netty.version>
3040-
<rspace-core-model.version>2.0.1</rspace-core-model.version>
3040+
<rspace-core-model.version>2.0.2-RSDEV-280-SNAPSHOT</rspace-core-model.version>
30413041
<servlet.version>3.1.0</servlet.version>
30423042
<sitemesh.version>2.4.2</sitemesh.version>
30433043
<urlrewrite.version>4.0.3</urlrewrite.version>

src/main/java/com/researchspace/api/v1/model/ApiInventoryBulkOperationResult.java

+9
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ public void addError(ApiError error) {
7474
errorCount++;
7575
}
7676

77+
public void addErrorWithRecord(ApiInventoryRecordInfo operationResult, ApiError error) {
78+
ApiInventoryBulkOperationRecordResult result =
79+
new ApiInventoryBulkOperationRecordResult(operationResult, error);
80+
result.record = operationResult;
81+
result.error = error;
82+
results.add(result);
83+
errorCount++;
84+
}
85+
7786
public void changeIntoErrorResult(ApiInventoryBulkOperationRecordResult result, ApiError error) {
7887
result.record = null;
7988
result.error = error;

src/main/java/com/researchspace/api/v1/model/ApiSample.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/** RSpace Inventory API Access your RSpace Inventory programmatically. */
22
package com.researchspace.api.v1.model;
33

4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
45
import com.fasterxml.jackson.annotation.JsonProperty;
56
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
67
import com.researchspace.model.inventory.Sample;
78
import com.researchspace.model.inventory.SubSample;
8-
import java.util.ArrayList;
9+
import java.util.LinkedList;
910
import java.util.List;
1011
import lombok.Data;
1112
import lombok.EqualsAndHashCode;
@@ -28,6 +29,7 @@
2829
"lastModified",
2930
"modifiedBy",
3031
"modifiedByFullName",
32+
"canBeDeleted",
3133
"deleted",
3234
"deletedDate",
3335
"iconId",
@@ -56,19 +58,33 @@
5658
"fields",
5759
"extraFields",
5860
"subSamples",
61+
"subSamplesIntoContainer",
5962
"_links"
6063
})
64+
@JsonIgnoreProperties(ignoreUnknown = true)
6165
public class ApiSample extends ApiSampleWithoutSubSamples {
6266

6367
@JsonProperty("subSamples")
64-
private List<ApiSubSampleInfo> subSamples = new ArrayList<>();
68+
private List<ApiSubSampleInfo> subSamples = new LinkedList<>();
69+
70+
@JsonProperty("subSamplesIntoContainer")
71+
private List<ApiSubSampleInfo> subSamplesIntoContainer = new LinkedList<>();
72+
73+
/* this will be `true` only when `subSamplesIntoContainer` is null or empty */
74+
@JsonProperty("canBeDeleted")
75+
private Boolean canBeDeleted;
6576

6677
public ApiSample(Sample sample) {
6778
super(sample);
6879

6980
for (SubSample subSample : sample.getActiveSubSamples()) {
70-
subSamples.add(new ApiSubSampleInfo(subSample));
81+
ApiSubSampleInfo subSampInfo = new ApiSubSampleInfo(subSample);
82+
this.subSamples.add(subSampInfo);
83+
if (subSample.isStoredInContainer()) {
84+
this.subSamplesIntoContainer.add(subSampInfo);
85+
}
7186
}
87+
this.canBeDeleted = this.subSamplesIntoContainer.isEmpty();
7288
}
7389

7490
@Override

src/main/java/com/researchspace/api/v1/model/ApiSampleWithFullSubSamples.java

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/** RSpace Inventory API Access your RSpace Inventory programmatically. */
22
package com.researchspace.api.v1.model;
33

4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
45
import com.fasterxml.jackson.annotation.JsonProperty;
56
import com.fasterxml.jackson.annotation.JsonProperty.Access;
67
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@@ -61,6 +62,7 @@
6162
"subSamples",
6263
"_links"
6364
})
65+
@JsonIgnoreProperties(ignoreUnknown = true)
6466
public class ApiSampleWithFullSubSamples extends ApiSampleWithoutSubSamples {
6567

6668
@JsonProperty("subSamples")

src/main/java/com/researchspace/service/inventory/impl/InventoryBulkOperationHandler.java

+17-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.researchspace.api.v1.model.ApiInventoryBulkOperationResult;
1212
import com.researchspace.api.v1.model.ApiInventoryRecordInfo;
1313
import com.researchspace.api.v1.model.ApiInventoryRecordInfo.ApiInventoryRecordType;
14+
import com.researchspace.api.v1.model.ApiSample;
1415
import com.researchspace.api.v1.model.ApiSampleInfo;
1516
import com.researchspace.api.v1.model.ApiSampleTemplate;
1617
import com.researchspace.api.v1.model.ApiSampleWithFullSubSamples;
@@ -104,7 +105,6 @@ public ApiInventoryBulkOperationResult runBulkOperation(
104105
private ApiInventoryBulkOperationResult runOperationForEachRecordFromBulkList(
105106
InventoryBulkOperationConfig bulkOpConfig,
106107
BiFunction<ApiInventoryRecordInfo, User, ApiInventoryRecordInfo> operation) {
107-
108108
ApiInventoryBulkOperationResult result = new ApiInventoryBulkOperationResult();
109109
List<ApiInventoryRecordInfo> records = bulkOpConfig.getRecords();
110110
User user = bulkOpConfig.getUser();
@@ -117,8 +117,23 @@ private ApiInventoryBulkOperationResult runOperationForEachRecordFromBulkList(
117117
}
118118
ApiInventoryRecordInfo operationResult = operation.apply(recInfo, user);
119119
if (operationResult != null) {
120-
result.addSuccessResult(operationResult);
120+
/* manage Sample deletion */
121+
if (operationResult.getClass().isInstance(ApiSample.class)) {
122+
ApiSample apiSample = (ApiSample) operationResult;
123+
if (!apiSample.getCanBeDeleted()) {
124+
ApiError err =
125+
new ApiError(
126+
HttpStatus.NOT_ACCEPTABLE,
127+
ApiErrorCodes.CONSTRAINT_VIOLATION.getCode(),
128+
"Errors detected : 1",
129+
"The Sample had got at least one active Subsample(s) located in a"
130+
+ " container");
131+
result.addErrorWithRecord(operationResult, err);
132+
continue;
133+
}
134+
}
121135
}
136+
result.addSuccessResult(operationResult);
122137
} catch (Exception e) {
123138
ApiError error = convertExceptionToApiError(e);
124139
result.addError(error);

src/main/java/com/researchspace/service/inventory/impl/SampleApiManagerImpl.java

+19-31
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.researchspace.service.inventory.impl;
22

33
import com.axiope.search.InventorySearchConfig.InventorySearchDeletedOption;
4-
import com.researchspace.api.v1.auth.ApiRuntimeException;
54
import com.researchspace.api.v1.model.ApiFieldToModelFieldFactory;
65
import com.researchspace.api.v1.model.ApiInventoryRecordInfo;
76
import com.researchspace.api.v1.model.ApiInventorySearchResult;
@@ -34,6 +33,7 @@
3433
import com.researchspace.model.inventory.Container;
3534
import com.researchspace.model.inventory.Container.ContainerType;
3635
import com.researchspace.model.inventory.InventoryRecord;
36+
import com.researchspace.model.inventory.MovableInventoryRecord;
3737
import com.researchspace.model.inventory.Sample;
3838
import com.researchspace.model.inventory.SampleSeriesHelper2;
3939
import com.researchspace.model.inventory.SubSample;
@@ -594,43 +594,31 @@ public ApiSample markSampleAsDeleted(Long sampleId, boolean forceDelete, User us
594594
try {
595595
dbSample = getIfExists(dbSample.getId());
596596
if (!dbSample.isDeleted()) {
597-
/* first try deleting undeleted subsamples */
598-
if (!forceDelete) {
599-
long ssInContainersCount =
600-
dbSample.getActiveSubSamples().stream()
601-
.filter(
602-
ss ->
603-
ss.getParentContainer() != null
604-
&& !ContainerType.WORKBENCH.equals(
605-
ss.getParentContainer().getContainerType()))
606-
.count();
607-
if (ssInContainersCount > 0) {
608-
throw new ApiRuntimeException(
609-
"sample.deletion.failure.subsamples.in.containers",
610-
dbSample.getGlobalIdentifier(),
611-
ssInContainersCount);
612-
}
597+
long ssInContainersCount =
598+
dbSample.getActiveSubSamples().stream()
599+
.filter(MovableInventoryRecord::isStoredInContainer)
600+
.count();
601+
if (forceDelete || ssInContainersCount == 0) {
602+
dbSample
603+
.getActiveSubSamples()
604+
.forEach(ss -> subSampleMgr.markSubSampleAsDeleted(ss.getId(), user, true));
605+
dbSample.refreshActiveSubSamples();
606+
dbSample.recalculateTotalQuantity();
607+
608+
/* then delete the sample */
609+
dbSample.setRecordDeleted(true);
610+
dbSample = sampleDao.save(dbSample);
611+
publisher.publishEvent(new InventoryDeleteEvent(dbSample, user));
613612
}
614-
dbSample
615-
.getActiveSubSamples()
616-
.forEach(ss -> subSampleMgr.markSubSampleAsDeleted(ss.getId(), user, true));
617-
dbSample.refreshActiveSubSamples();
618-
dbSample.recalculateTotalQuantity();
619-
620-
/* then delete the sample */
621-
dbSample.setRecordDeleted(true);
622-
dbSample = sampleDao.save(dbSample);
623-
publisher.publishEvent(new InventoryDeleteEvent(dbSample, user));
624613
}
625614
} finally {
626615
if (temporaryLock) {
627616
unlockItemAfterEdit(dbSample, user);
628617
}
629618
}
630-
631-
ApiSample deleted = getOutgoingApiSample(dbSample, user);
632-
updateOntologyOnRecordChanges(deleted, user);
633-
return deleted;
619+
ApiSample apiSampleResult = getOutgoingApiSample(dbSample, user);
620+
updateOntologyOnRecordChanges(apiSampleResult, user);
621+
return apiSampleResult;
634622
}
635623

636624
@Override

src/main/java/com/researchspace/webapp/controller/ServiceLoggerAspct.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ protected String methodInfo(ProceedingJoinPoint jp, String methodName) {
101101
MethodSignature methodSignature = (MethodSignature) jp.getSignature();
102102
if (shouldSkipMethodArgs(methodSignature)) {
103103
return String.format(
104-
"In method [%s] in class [%s] (args hidden)", methodName, jp.getSignature().getDeclaringTypeName());
104+
"In method [%s] in class [%s] (args hidden)",
105+
methodName, jp.getSignature().getDeclaringTypeName());
105106
}
106107
return String.format(
107108
"In method [%s] in class [%s] with args: %s",

src/main/resources/bundles/inventory/inventory.properties

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# inventory API error messages
2-
3-
sample.deletion.failure.subsamples.in.containers=Sample {0} has {1} subsample(s) currently stored inside containers
42
container.deletion.failure.not.empty=Container {0} is not empty and cannot be deleted
53

64
move.failure.no.target.location.for.grid.image.container=When moving to image/grid type container request has to specify target location

src/test/java/com/researchspace/service/ExternalMessageHandlerImplTest.java

-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.researchspace.model.views.ServiceOperationResult;
1111
import com.researchspace.service.impl.ConditionalTestRunner;
1212
import com.researchspace.service.impl.RunIfSystemPropertyDefined;
13-
import com.researchspace.slack.SlackPosterTest;
1413
import com.researchspace.testutils.RSpaceTestUtils;
1514
import com.researchspace.testutils.SpringTransactionalTest;
1615
import java.util.HashMap;
@@ -159,5 +158,4 @@ private Map<String, String> getMsTeamsCfg() {
159158
map.put("MSTEAMS_WEBHOOK_URL", msTeamsTestWebhookUrl);
160159
return map;
161160
}
162-
163161
}

src/test/java/com/researchspace/service/inventory/SampleApiManagerTest.java

+3-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import com.axiope.search.InventorySearchConfig.InventorySearchDeletedOption;
1212
import com.axiope.search.SearchUtils;
1313
import com.researchspace.Constants;
14-
import com.researchspace.api.v1.auth.ApiRuntimeException;
1514
import com.researchspace.api.v1.model.ApiContainer;
1615
import com.researchspace.api.v1.model.ApiExtraField;
1716
import com.researchspace.api.v1.model.ApiExtraField.ExtraFieldTypeEnum;
@@ -581,13 +580,9 @@ public void deleteSample() {
581580
assertEquals(initialSampleCountIncludingDeleted + 1, afterCreationSampleCountIncludingDeleted);
582581

583582
// try deleting without forceDelete flag
584-
ApiRuntimeException are =
585-
assertThrows(
586-
ApiRuntimeException.class,
587-
() -> sampleApiMgr.markSampleAsDeleted(newSample.getId(), false, testUser));
588-
assertEquals("sample.deletion.failure.subsamples.in.containers", are.getErrorCode());
589-
assertEquals(newSample.getGlobalId(), are.getArgs()[0]);
590-
assertEquals(1L, are.getArgs()[1]);
583+
ApiSample apiSample = sampleApiMgr.markSampleAsDeleted(newSample.getId(), false, testUser);
584+
assertFalse(apiSample.getCanBeDeleted());
585+
assertEquals(1, apiSample.getSubSamplesIntoContainer().size());
591586
listContainer = containerApiMgr.getApiContainerById(listContainer.getId(), testUser);
592587
assertEquals(1, listContainer.getContentSummary().getTotalCount());
593588
Mockito.verify(mockPublisher, Mockito.never())

src/test/java/com/researchspace/slack/SlackPosterTest.java

-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.fasterxml.jackson.databind.ObjectMapper;
88
import com.fasterxml.jackson.databind.node.ObjectNode;
99
import com.researchspace.service.impl.ConditionalTestRunner;
10-
import com.researchspace.service.impl.ConditionalTestRunnerNotSpring;
1110
import com.researchspace.service.impl.RunIfSystemPropertyDefined;
1211
import com.researchspace.session.SessionTimeZoneUtils;
1312
import com.researchspace.testutils.SpringTransactionalTest;
@@ -74,6 +73,4 @@ public void testSlackTemplate() throws URISyntaxException, JsonProcessingExcepti
7473
assertEquals(HttpStatus.OK, resp.getStatusCode());
7574
System.err.println(resp);
7675
}
77-
78-
7976
}

src/test/java/com/researchspace/webapp/integrations/dmptool/DMPToolOAuthControllerMVCIT.java

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import com.researchspace.dmptool.model.DMPList;
1414
import com.researchspace.dmptool.model.DMPPlanScope;
1515
import com.researchspace.dmptool.model.DMPToolDMP;
16-
import com.researchspace.model.User;
1716
import com.researchspace.model.dmps.DMPUser;
1817
import com.researchspace.service.impl.ConditionalTestRunner;
1918
import com.researchspace.service.impl.RunIfSystemPropertyDefined;

0 commit comments

Comments
 (0)