diff --git a/ramls/acq-models b/ramls/acq-models index 512a2d5fc..25083ed83 160000 --- a/ramls/acq-models +++ b/ramls/acq-models @@ -1 +1 @@ -Subproject commit 512a2d5fc83bc2c4784d1abb4b28b1449c175fdd +Subproject commit 25083ed834962a4b9423b33b4b307f86a2e4918b diff --git a/src/main/java/org/folio/helper/BindHelper.java b/src/main/java/org/folio/helper/BindHelper.java index 0efc0dc3b..a576bf85e 100644 --- a/src/main/java/org/folio/helper/BindHelper.java +++ b/src/main/java/org/folio/helper/BindHelper.java @@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; @@ -55,10 +56,8 @@ public BindHelper(BindPiecesCollection bindPiecesCollection, bindPiecesCollection.getPoLineId(), bindPiecesCollection.getBindPieceIds().size()); } - public BindHelper(String pieceId, Map okapiHeaders, Context ctx) { + public BindHelper(Map okapiHeaders, Context ctx) { super(okapiHeaders, ctx); - piecesByLineId = null; - logger.debug("Piece {} is going to have binding removed", pieceId); } private Map> groupBindPieceByPoLineId(BindPiecesCollection bindPiecesCollection) { @@ -73,12 +72,19 @@ private Map> groupBindPieceByPoLineId( } public Future removeBinding(String pieceId, RequestContext requestContext) { - return removeForbiddenEntities(requestContext) - .compose(v -> pieceStorageService.getPieceById(pieceId, requestContext)) - .map(piece -> piece.withBindItemId(null).withIsBound(false)) - .map(piece -> Map.of(piece.getPoLineId(), List.of(piece))) - .compose(piecesGroupedByPoLine -> storeUpdatedPieceRecords(piecesGroupedByPoLine, requestContext)) - .mapEmpty(); + logger.debug("removeBinding:: Removing binding for piece: {}", pieceId); + return pieceStorageService.getPieceById(pieceId, requestContext) + .compose(piece -> { + // Populate piecesByLineId to accommodate helper methods + piecesByLineId = Map.of(piece.getPoLineId(), Collections.singletonMap(piece.getId(), null)); + // Remove binding for the piece + piece.withBindItemId(null).withIsBound(false); + // Update piece record + return removeForbiddenEntities(requestContext) + .compose(v -> getValidPieces(requestContext)) + .compose(piecesGroupedByPoLine -> storeUpdatedPieceRecords(piecesGroupedByPoLine, requestContext)) + .mapEmpty(); + }); } public Future bindPieces(BindPiecesCollection bindPiecesCollection, RequestContext requestContext) { diff --git a/src/main/java/org/folio/rest/impl/ReceivingAPI.java b/src/main/java/org/folio/rest/impl/ReceivingAPI.java index 5ad36fff9..6d6b62e81 100644 --- a/src/main/java/org/folio/rest/impl/ReceivingAPI.java +++ b/src/main/java/org/folio/rest/impl/ReceivingAPI.java @@ -82,9 +82,9 @@ public void postOrdersBindPieces(BindPiecesCollection entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { logger.info("Removing binding for piece: {}", id); - BindHelper helper = new BindHelper(id, okapiHeaders, vertxContext); + BindHelper helper = new BindHelper(okapiHeaders, vertxContext); helper.removeBinding(id, new RequestContext(vertxContext, okapiHeaders)) - .onSuccess(result -> asyncResultHandler.handle(succeededFuture(helper.buildOkResponse(result)))) + .onSuccess(s -> asyncResultHandler.handle(succeededFuture(helper.buildNoContentResponse()))) .onFailure(t -> handleErrorResponse(asyncResultHandler, helper, t)); } diff --git a/src/test/java/org/folio/TestConstants.java b/src/test/java/org/folio/TestConstants.java index 92e445927..96007b3c9 100644 --- a/src/test/java/org/folio/TestConstants.java +++ b/src/test/java/org/folio/TestConstants.java @@ -21,6 +21,7 @@ private TestConstants() {} public static final String ORDERS_CHECKIN_ENDPOINT = "/orders/check-in"; public static final String ORDERS_EXPECT_ENDPOINT = "/orders/expect"; public static final String ORDERS_BIND_ENDPOINT = "/orders/bind-pieces"; + public static final String ORDERS_BIND_ID_ENDPOINT = "/orders/bind-pieces/%s"; public static final String PO_LINE_NUMBER_VALUE = "1"; public static final String BAD_QUERY = "unprocessableQuery"; diff --git a/src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java b/src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java index 28fa50434..b7daec18d 100644 --- a/src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java +++ b/src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java @@ -42,6 +42,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -55,12 +56,14 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static org.folio.RestTestUtils.prepareHeaders; +import static org.folio.RestTestUtils.verifyDeleteResponse; import static org.folio.RestTestUtils.verifyPostResponse; import static org.folio.TestConfig.clearServiceInteractions; import static org.folio.TestConfig.initSpringContext; import static org.folio.TestConfig.isVerticleNotDeployed; import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10; import static org.folio.TestConstants.ORDERS_BIND_ENDPOINT; +import static org.folio.TestConstants.ORDERS_BIND_ID_ENDPOINT; import static org.folio.TestConstants.ORDERS_CHECKIN_ENDPOINT; import static org.folio.TestConstants.ORDERS_EXPECT_ENDPOINT; import static org.folio.TestConstants.ORDERS_RECEIVING_ENDPOINT; @@ -118,6 +121,7 @@ import static org.folio.service.inventory.InventoryItemManager.ITEM_DISPLAY_SUMMARY; import static org.folio.service.inventory.InventoryItemManager.ITEM_ENUMERATION; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.emptyString; import static org.hamcrest.Matchers.equalTo; @@ -1291,6 +1295,61 @@ void testBindExpectedPieces() { assertThat(errors.get(0).getMessage(), equalTo(PIECES_MUST_HAVE_RECEIVED_STATUS.getDescription())); } + @Test + void testRemovePieceBinding() { + logger.info("=== Test DELETE Remove binding"); + + var holdingId = "849241fa-4a14-4df5-b951-846dcd6cfc4d"; + var order = getMinimalContentCompositePurchaseOrder() + .withWorkflowStatus(CompositePurchaseOrder.WorkflowStatus.OPEN); + var poLine = getMinimalContentCompositePoLine(order.getId()); + var bindingPiece = getMinimalContentPiece(poLine.getId()) + .withHoldingId(holdingId) + .withReceivingStatus(Piece.ReceivingStatus.RECEIVED) + .withFormat(Piece.Format.PHYSICAL); + + addMockEntry(PURCHASE_ORDER_STORAGE, order); + addMockEntry(PO_LINES_STORAGE, poLine); + addMockEntry(PIECES_STORAGE, bindingPiece); + addMockEntry(TITLES, getTitle(poLine)); + + var bindPiecesCollection = new BindPiecesCollection() + .withPoLineId(poLine.getId()) + .withBindItem(getMinimalContentBindItem() + .withLocationId(null) + .withHoldingId(holdingId)) + .withBindPieceIds(List.of(bindingPiece.getId())); + + var bindResponse = verifyPostResponse(ORDERS_BIND_ENDPOINT, JsonObject.mapFrom(bindPiecesCollection).encode(), + prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10), APPLICATION_JSON, HttpStatus.HTTP_OK.toInt()) + .as(BindPiecesResult.class); + + assertThat(bindResponse.getPoLineId(), is(poLine.getId())); + assertThat(bindResponse.getBoundPieceIds(), contains(bindingPiece.getId())); + assertThat(bindResponse.getItemId(), notNullValue()); + + var url = String.format(ORDERS_BIND_ID_ENDPOINT, bindingPiece.getId()); + verifyDeleteResponse(url, "", HttpStatus.HTTP_NO_CONTENT.toInt()); + + var pieceUpdates = getPieceUpdates(); + assertThat(pieceUpdates, notNullValue()); + assertThat(pieceUpdates, hasSize(2)); + + var pieceList = pieceUpdates.stream() + .map(json -> json.mapTo(Piece.class)) + .filter(piece -> Objects.equals(bindingPiece.getId(), piece.getId())) + .sorted(Comparator.comparing(Piece::getIsBound)) + .toList(); + + assertThat(pieceList.size(), is(2)); + var pieceBefore = pieceList.get(1); + assertThat(pieceBefore.getIsBound(), is(true)); + assertThat(pieceBefore.getBindItemId(), notNullValue()); + var pieceAfter = pieceList.get(0); + assertThat(pieceAfter.getIsBound(), is(false)); + assertThat(pieceAfter.getBindItemId(), nullValue()); + } + @Test void testPostReceivingWithErrorSearchingForPiece() { logger.info("=== Test POST Receiving - Receive resources with error searching for piece");