Skip to content

Commit

Permalink
MODINV-883 Set instance record as deleted (#663)
Browse files Browse the repository at this point in the history
* add soft delete endpoint in Instances

* todo comment

* upd news
  • Loading branch information
JavokhirAbdullayev authored Jan 9, 2024
1 parent 8c6cfb6 commit 6a6ffef
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 11 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 20.2.0-SNAPSHOT 2023-xx-xx
* Inventory cannot process Holdings with virtual fields ([MODINV-941](https://issues.folio.org/browse/MODINV-941))
* Set instance record as deleted ([MODINV-883](https://issues.folio.org/browse/MODINV-883))

## 20.1.0 2023-10-13
* Update status when user attempts to update shared auth record from member tenant ([MODDATAIMP-926](https://issues.folio.org/browse/MODDATAIMP-926))
Expand Down
39 changes: 28 additions & 11 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"inventory-storage.instances.item.get",
"inventory-storage.bound-with-parts.collection.get"
]
}, {
},
{
"methods": ["GET"],
"pathPattern": "/inventory/items/{id}",
"permissionsRequired": ["inventory.items.item.get"],
Expand Down Expand Up @@ -297,7 +298,8 @@
"inventory-storage.bound-with-parts.collection.get",
"users.item.get"
]
}, {
},
{
"methods": ["PUT"],
"pathPattern": "/inventory/items/{id}",
"permissionsRequired": ["inventory.items.item.put"],
Expand All @@ -313,20 +315,23 @@
"pathPattern": "/inventory/items/{id}",
"permissionsRequired": ["inventory.items.item.delete"],
"modulePermissions": ["inventory-storage.items.item.delete"]
}, {
},
{
"methods": ["DELETE"],
"pathPattern": "/inventory/items",
"permissionsRequired": ["inventory.items.collection.delete"],
"modulePermissions": ["inventory-storage.items.collection.delete"]
}, {
},
{
"methods": ["PUT"],
"pathPattern": "/inventory/holdings/{id}",
"permissionsRequired": ["inventory.holdings.item.put"],
"modulePermissions": [
"inventory-storage.holdings.item.get",
"inventory-storage.holdings.item.put"
]
}, {
},
{
"methods": ["GET"],
"pathPattern": "/inventory/instances",
"permissionsRequired": ["inventory.instances.collection.get"],
Expand All @@ -339,7 +344,8 @@
"inventory-storage.holdings.collection.get",
"inventory-storage.items.collection.get"
]
}, {
},
{
"methods": ["GET"],
"pathPattern": "/inventory/items-by-holdings-id",
"permissionsRequired": ["inventory.items.collection.get"],
Expand All @@ -358,7 +364,8 @@
"inventory-storage.instances.collection.get",
"inventory-storage.instances.item.get"
]
}, {
},
{
"methods": ["GET"],
"pathPattern": "/inventory/instances/{id}",
"permissionsRequired": ["inventory.instances.item.get"],
Expand All @@ -370,7 +377,8 @@
"inventory-storage.holdings.collection.get",
"inventory-storage.items.collection.get"
]
}, {
},
{
"methods": ["POST"],
"pathPattern": "/inventory/instances",
"permissionsRequired": ["inventory.instances.item.post"],
Expand All @@ -386,7 +394,8 @@
"inventory-storage.instance-relationships.item.put",
"inventory-storage.instance-relationships.item.delete"
]
}, {
},
{
"methods": ["PUT"],
"pathPattern": "/inventory/instances/{id}",
"permissionsRequired": ["inventory.instances.item.put"],
Expand All @@ -405,16 +414,24 @@
"inventory-storage.instance-relationships.item.put",
"inventory-storage.instance-relationships.item.delete"
]
}, {
},
{
"methods": ["DELETE"],
"pathPattern": "/inventory/instances/{id}",
"permissionsRequired": ["inventory.instances.item.delete"],
"modulePermissions": ["inventory-storage.instances.item.delete"]
}, {
},
{
"methods": ["DELETE"],
"pathPattern": "/inventory/instances",
"permissionsRequired": ["inventory.instances.collection.delete"],
"modulePermissions": ["inventory-storage.instances.collection.delete"]
},
{
"methods": ["DELETE"],
"pathPattern": "/inventory/instances/{id}/mark-deleted",
"permissionsRequired": [],
"modulePermissions": []
}
]
},
Expand Down
22 changes: 22 additions & 0 deletions ramls/inventory.raml
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,26 @@ resourceTypes:
get:
put:
is: [validate]
/mark-deleted:
delete:
description: Toggle the suppression state of an instance record, affecting either instance and associated MARC record if present.
responses:
204:
description: Instance marked as deleted.
404:
description: "Instance not found"
body:
text/plain:
example: "Instance with such id not found"
422:
description: "Validation error"
body:
application/json:
type: errors
500:
description: "Internal server error"
body:
text/plain:
example: "Internal server error"


29 changes: 29 additions & 0 deletions src/main/java/org/folio/inventory/resources/Instances.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public void register(Router router) {
router.get(INSTANCES_PATH + "/:id").handler(this::getById);
router.put(INSTANCES_PATH + "/:id").handler(this::update);
router.delete(INSTANCES_PATH + "/:id").handler(this::deleteById);
router.delete(INSTANCES_PATH + "/:id" + "/mark-deleted").handler(this::softDelete);
}

private void getAll(RoutingContext routingContext) {
Expand Down Expand Up @@ -302,6 +303,34 @@ private void deleteById(RoutingContext routingContext) {
FailureResponseConsumer.serverError(routingContext.response()));
}

private void softDelete(RoutingContext routingContext) {
WebContext webContext = new WebContext(routingContext);
InstanceCollection instanceCollection = storage.getInstanceCollection(webContext);
instanceCollection.findById(routingContext.request().getParam("id"),
it -> {
Instance instance = it.getResult();
if (instance != null) {
updateVisibility(instance, routingContext, instanceCollection);
if (isInstanceControlledByRecord(instance)) {
updateSuppressFromDiscoveryFlag(webContext, instance); //todo: will be replaced by soft delete by instance
}
} else {
ClientErrorResponse.notFound(routingContext.response());
}
}, FailureResponseConsumer.serverError(routingContext.response()));
}

private void updateVisibility(Instance instance, RoutingContext routingContext, InstanceCollection instanceCollection) {
instance.setDiscoverySuppress(true);
instance.setStaffSuppress(true);
instanceCollection.update(instance, v -> {
log.info("staffSuppress and discoverySuppress properties are set to true for instance {}",
instance.getId());
noContent(routingContext.response());
},
FailureResponseConsumer.serverError(routingContext.response()));
}

private void getById(RoutingContext routingContext) {
WebContext context = new WebContext(routingContext);

Expand Down
26 changes: 26 additions & 0 deletions src/test/java/api/InstancesApiExamples.java
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,32 @@ public void canDeleteAnInstance()
assertThat(getAllResponse.getJson().getInteger("totalRecords"), is(2));
}

@Test
@SneakyThrows
public void canSoftDeleteInstance() {
JsonObject instanceToDelete = createInstance(marcInstanceWithDefaultBlockedFields(UUID.randomUUID()));

URL softDeleteUrl = new URL(String.format("%s/%s/%s",
ApiRoot.instances(), instanceToDelete.getString("id"), "mark-deleted" ));

URL getByIdUrl = new URL(String.format("%s/%s",
ApiRoot.instances(), instanceToDelete.getString("id")));

final var deleteCompleted = okapiClient.delete(softDeleteUrl);

Response deleteResponse = deleteCompleted.toCompletableFuture().get(5, SECONDS);

assertThat(deleteResponse.getStatusCode(), is(204));
assertThat(deleteResponse.hasBody(), is(false));

final var getCompleted = okapiClient.get(getByIdUrl);

Response getResponse = getCompleted.toCompletableFuture().get(5, SECONDS);

assertTrue(getResponse.getJson().getBoolean("staffSuppress"));
assertTrue(getResponse.getJson().getBoolean("discoverySuppress"));
}

@Test
public void canGetAllInstances()
throws InterruptedException,
Expand Down

0 comments on commit 6a6ffef

Please sign in to comment.