From eda88e0963ffac8142901b2e50188a06593ad047 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:09:26 -0400 Subject: [PATCH 01/22] draft --- .../java/org/folio/rest/impl/PiecesAPI.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index 968aa9c8b..ed60fbdbe 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -2,10 +2,14 @@ import static io.vertx.core.Future.succeededFuture; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.ws.rs.core.Response; +import io.vertx.core.CompositeFuture; +import io.vertx.core.Future; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -96,4 +100,26 @@ public void deleteOrdersPiecesById(String pieceId, boolean deleteHolding, Map asyncResultHandler.handle(succeededFuture(buildNoContentResponse()))) .onFailure(fail -> handleErrorResponse(asyncResultHandler, fail)); } + + @Override + @Validate + public void deleteOrdersPiecesBulk(List ids, boolean deleteHolding, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + List deleteFutures = ids.stream() + .map(id -> pieceDeleteFlowManager.deletePiece(id, deleteHolding, new RequestContext(vertxContext, okapiHeaders)) + .onFailure(t -> { + logger.error("Failed to delete piece with ID: " + id, t); + }) + .mapEmpty()) + .collect(Collectors.toList()); + + CompositeFuture.join(deleteFutures).onComplete(ar -> { + if (ar.succeeded()) { + asyncResultHandler.handle(Future.succeededFuture(buildNoContentResponse())); + } else { + handleErrorResponse(asyncResultHandler, new Throwable("Error deleting multiple pieces")); + } + }); + } } + From e64274cc68b85596e63a0960e0d61184b2c7da5d Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Thu, 18 Apr 2024 21:39:09 -0400 Subject: [PATCH 02/22] remove the overide --- src/main/java/org/folio/rest/impl/PiecesAPI.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index ed60fbdbe..0e146153e 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -101,18 +101,13 @@ public void deleteOrdersPiecesById(String pieceId, boolean deleteHolding, Map handleErrorResponse(asyncResultHandler, fail)); } - @Override - @Validate public void deleteOrdersPiecesBulk(List ids, boolean deleteHolding, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { List deleteFutures = ids.stream() .map(id -> pieceDeleteFlowManager.deletePiece(id, deleteHolding, new RequestContext(vertxContext, okapiHeaders)) - .onFailure(t -> { - logger.error("Failed to delete piece with ID: " + id, t); - }) + .onFailure(t -> {logger.error("Failed to delete piece with ID: " + id, t);}) .mapEmpty()) .collect(Collectors.toList()); - CompositeFuture.join(deleteFutures).onComplete(ar -> { if (ar.succeeded()) { asyncResultHandler.handle(Future.succeededFuture(buildNoContentResponse())); From 28f1b6cda81fce2e798bd3fd748a391b460ac06b Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Fri, 19 Apr 2024 09:12:17 -0400 Subject: [PATCH 03/22] coding format correct --- src/main/java/org/folio/rest/impl/PiecesAPI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index 0e146153e..378bd5135 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -102,7 +102,7 @@ public void deleteOrdersPiecesById(String pieceId, boolean deleteHolding, Map ids, boolean deleteHolding, Map okapiHeaders, - Handler> asyncResultHandler, Context vertxContext) { + Handler> asyncResultHandler, Context vertxContext) { List deleteFutures = ids.stream() .map(id -> pieceDeleteFlowManager.deletePiece(id, deleteHolding, new RequestContext(vertxContext, okapiHeaders)) .onFailure(t -> {logger.error("Failed to delete piece with ID: " + id, t);}) From 72ac005382502fd0b685348c8a980726afcd7648 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Thu, 25 Apr 2024 12:55:03 -0400 Subject: [PATCH 04/22] modify pieces.rml, PiecesAPI.java --- ramls/pieces.raml | 35 ++++++++++++++++++- .../java/org/folio/rest/impl/PiecesAPI.java | 17 +++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/ramls/pieces.raml b/ramls/pieces.raml index 6cdb65a4c..2111b6c19 100644 --- a/ramls/pieces.raml +++ b/ramls/pieces.raml @@ -6,7 +6,7 @@ protocols: [ HTTP, HTTPS ] documentation: - title: Orders Business Logic API - content: API for managing pieces + content: API for managing pieces including batch operations for deletion. types: piece: !include acq-models/mod-orders-storage/schemas/piece.json @@ -47,6 +47,39 @@ resourceTypes: example: true required: false default: false + /batch/PiecesCollection: + delete: + description: Batch delete pieces + queryParameters: + deleteHolding: + displayName: Delete associated holdings + type: boolean + description: Specify whether to delete associated holdings for the pieces in the batch + example: true + required: false + default: false + body: + application/json: + type: piece-collection + example: !include acq-models/mod-orders-storage/examples/piece_collection.sample + responses: + 204: + description: "Batch delete of pieces successfully completed" + 400: + description: "Bad request, e.g., malformed JSON or validation failed" + body: + application/json: + type: errors + 404: + description: "One or more pieces not found" + body: + application/json: + type: errors + 500: + description: "Internal server error, e.g. due to misconfiguration" + body: + application/json: + type: errors /{id}: uriParameters: id: diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index 378bd5135..64b34a128 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -16,6 +16,7 @@ import org.folio.rest.annotations.Validate; import org.folio.rest.core.models.RequestContext; import org.folio.rest.jaxrs.model.Piece; +import org.folio.rest.jaxrs.model.PieceCollection; import org.folio.rest.jaxrs.resource.OrdersPieces; import org.folio.service.pieces.PieceStorageService; import org.folio.service.pieces.flows.create.PieceCreateFlowManager; @@ -70,6 +71,22 @@ public void postOrdersPieces(boolean createItem, Piece entity, Map handleErrorResponse(asyncResultHandler, t)); } + @Override + public void deleteOrdersPiecesBatchPiecesCollection(boolean deleteHolding, PieceCollection entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { + List deleteFutures = entity.getPieces().stream() + .map(piece -> pieceDeleteFlowManager.deletePiece(piece.getId(), deleteHolding, new RequestContext(vertxContext, okapiHeaders)) + .onFailure(t -> logger.error("Failed to delete piece with ID: " + piece.getId(), t)) + .mapEmpty()) + .collect(Collectors.toList()); + CompositeFuture.join(deleteFutures).onComplete(ar -> { + if (ar.succeeded()) { + asyncResultHandler.handle(Future.succeededFuture(buildNoContentResponse())); + } else { + handleErrorResponse(asyncResultHandler, new Throwable("Error deleting multiple pieces")); + } + }); + } + @Override @Validate public void getOrdersPiecesById(String id, Map okapiHeaders, From f01b393c543b897397237857b5a9aef886d67fb9 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 30 Apr 2024 09:21:25 -0400 Subject: [PATCH 05/22] modify pieces.rml, PiecesAPI.java, add unit test, add batch delete in deleflowManager --- ramls/pieces.raml | 51 ++++++++--------- .../orders/utils/ResourcePathResolver.java | 2 + .../java/org/folio/rest/impl/PiecesAPI.java | 45 +++++---------- .../flows/delete/PieceDeleteFlowManager.java | 24 ++++++++ src/test/java/org/folio/RestTestUtils.java | 23 ++++++++ .../delete/PieceDeleteFlowManagerTest.java | 56 +++++++++++++++++++ 6 files changed, 145 insertions(+), 56 deletions(-) diff --git a/ramls/pieces.raml b/ramls/pieces.raml index 2111b6c19..5bab0b52f 100644 --- a/ramls/pieces.raml +++ b/ramls/pieces.raml @@ -50,36 +50,37 @@ resourceTypes: /batch/PiecesCollection: delete: description: Batch delete pieces - queryParameters: - deleteHolding: - displayName: Delete associated holdings - type: boolean - description: Specify whether to delete associated holdings for the pieces in the batch - example: true - required: false - default: false body: application/json: type: piece-collection example: !include acq-models/mod-orders-storage/examples/piece_collection.sample responses: - 204: - description: "Batch delete of pieces successfully completed" - 400: - description: "Bad request, e.g., malformed JSON or validation failed" - body: - application/json: - type: errors - 404: - description: "One or more pieces not found" - body: - application/json: - type: errors - 500: - description: "Internal server error, e.g. due to misconfiguration" - body: - application/json: - type: errors + 204: + description: "Batch delete of pieces successfully completed" + body: + text/plain: + example: "All pieces successfully deleted." + 400: + description: "Bad request, e.g., malformed JSON or validation failed" + body: + application/json: + type: errors + text/plain: + example: "Bad request - malformed JSON or validation failed." + 404: + description: "One or more pieces not found" + body: + application/json: + type: errors + text/plain: + example: "Error - one or more pieces not found." + 500: + description: "Internal server error, e.g. due to misconfiguration" + body: + application/json: + type: errors + text/plain: + example: "Internal server error - due to misconfiguration." /{id}: uriParameters: id: diff --git a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java index 4e29b8e7a..d20203741 100644 --- a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java +++ b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java @@ -23,6 +23,7 @@ private ResourcePathResolver() { public static final String REPORTING_CODES = "reportingCodes"; public static final String PURCHASE_ORDER_STORAGE = "purchaseOrder"; public static final String PIECES_STORAGE = "pieces"; + public static final String PIECES_COLLECTION_STORAGE = "PiecesCollection"; public static final String RECEIVING_HISTORY = "receiving-history"; public static final String RECEIPT_STATUS = "receiptStatus"; public static final String PAYMENT_STATUS = "paymentStatus"; @@ -94,6 +95,7 @@ private ResourcePathResolver() { apis.put(USERS, "/users"); apis.put(ORDER_SETTINGS, "/orders-storage/settings"); apis.put(ROUTING_LISTS, "/orders-storage/routing-lists"); + apis.put(PIECES_COLLECTION_STORAGE, "/orders-storage/pieces-collecton"); SUB_OBJECT_COLLECTION_APIS = Collections.unmodifiableMap(apis); SUB_OBJECT_ITEM_APIS = Collections.unmodifiableMap( diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index 64b34a128..d15e09654 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -2,9 +2,9 @@ import static io.vertx.core.Future.succeededFuture; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import javax.ws.rs.core.Response; @@ -43,6 +43,7 @@ public class PiecesAPI extends BaseApi implements OrdersPieces { @Autowired private PieceUpdateFlowManager pieceUpdateFlowManager; + public PiecesAPI() { SpringContextUtil.autowireDependencies(this, Vertx.currentContext()); } @@ -71,21 +72,7 @@ public void postOrdersPieces(boolean createItem, Piece entity, Map handleErrorResponse(asyncResultHandler, t)); } - @Override - public void deleteOrdersPiecesBatchPiecesCollection(boolean deleteHolding, PieceCollection entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - List deleteFutures = entity.getPieces().stream() - .map(piece -> pieceDeleteFlowManager.deletePiece(piece.getId(), deleteHolding, new RequestContext(vertxContext, okapiHeaders)) - .onFailure(t -> logger.error("Failed to delete piece with ID: " + piece.getId(), t)) - .mapEmpty()) - .collect(Collectors.toList()); - CompositeFuture.join(deleteFutures).onComplete(ar -> { - if (ar.succeeded()) { - asyncResultHandler.handle(Future.succeededFuture(buildNoContentResponse())); - } else { - handleErrorResponse(asyncResultHandler, new Throwable("Error deleting multiple pieces")); - } - }); - } + @Override @Validate @@ -112,26 +99,22 @@ public void putOrdersPiecesById(String pieceId, boolean createItem, boolean dele @Override @Validate public void deleteOrdersPiecesById(String pieceId, boolean deleteHolding, Map okapiHeaders, - Handler> asyncResultHandler, Context vertxContext) { + Handler> asyncResultHandler, Context vertxContext) { pieceDeleteFlowManager.deletePiece(pieceId, deleteHolding, new RequestContext(vertxContext, okapiHeaders)) .onSuccess(ok -> asyncResultHandler.handle(succeededFuture(buildNoContentResponse()))) .onFailure(fail -> handleErrorResponse(asyncResultHandler, fail)); + } - public void deleteOrdersPiecesBulk(List ids, boolean deleteHolding, Map okapiHeaders, - Handler> asyncResultHandler, Context vertxContext) { - List deleteFutures = ids.stream() - .map(id -> pieceDeleteFlowManager.deletePiece(id, deleteHolding, new RequestContext(vertxContext, okapiHeaders)) - .onFailure(t -> {logger.error("Failed to delete piece with ID: " + id, t);}) - .mapEmpty()) - .collect(Collectors.toList()); - CompositeFuture.join(deleteFutures).onComplete(ar -> { - if (ar.succeeded()) { - asyncResultHandler.handle(Future.succeededFuture(buildNoContentResponse())); - } else { - handleErrorResponse(asyncResultHandler, new Throwable("Error deleting multiple pieces")); - } - }); + @Override + @Validate + public void deleteOrdersPiecesBatchPiecesCollection(PieceCollection entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { + List pieceIds = new ArrayList<>(); + for (Piece piece : entity.getPieces()) { + pieceIds.add(piece.getId()); + } + pieceDeleteFlowManager.batchDeletePiece(pieceIds, new RequestContext(vertxContext, okapiHeaders)); + } } diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index aab0743ac..9c8d13431 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -7,7 +7,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; +import io.vertx.core.CompositeFuture; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; @@ -54,8 +56,12 @@ public PieceDeleteFlowManager(PieceStorageService pieceStorageService, Protectio public Future deletePiece(String pieceId, boolean deleteHolding, RequestContext requestContext) { PieceDeletionHolder holder = new PieceDeletionHolder().withDeleteHolding(deleteHolding); + + System.out.println("----------------------------------"+pieceId+"---------------------------------"); + return pieceStorageService.getPieceById(pieceId, requestContext) .map(pieceToDelete -> { + System.out.print("----------------------------------"+pieceId+"---------------------------------"); holder.withPieceToDelete(pieceToDelete); return null; }) .compose(aHolder -> basePieceFlowHolderBuilder.updateHolderWithOrderInformation(holder, requestContext)) @@ -140,4 +146,22 @@ private Future getOnOrderItemForPiece(Piece piece, RequestContext re return Future.succeededFuture(); } } + + public Future batchDeletePiece(List ids, RequestContext requestContext) { + + + // Print the IDs to track the pieces being deleted + ids.forEach(id -> System.out.println("----------------------------------" + id + "---------------------------------")); + + // Perform delete operations for each ID + List deleteFutures = ids.stream() + .map(id -> pieceStorageService.getPieceById(id, requestContext) + .onFailure(t -> logger.error("Failed to delete piece with ID: " + id, t)) // Log using the retrieved ID + .mapEmpty()) // Continue with empty to just track completion + .collect(Collectors.toList()); + + // Return a future to track completion + return CompositeFuture.all(deleteFutures).mapEmpty(); + } + } diff --git a/src/test/java/org/folio/RestTestUtils.java b/src/test/java/org/folio/RestTestUtils.java index 002952b6f..c268c452e 100644 --- a/src/test/java/org/folio/RestTestUtils.java +++ b/src/test/java/org/folio/RestTestUtils.java @@ -18,10 +18,12 @@ import java.util.Map; +import jakarta.validation.Payload; import org.apache.commons.lang3.StringUtils; import org.folio.orders.events.handlers.HandlersTestHelper; import org.folio.rest.jaxrs.model.Error; import org.folio.rest.jaxrs.model.Errors; +import org.folio.rest.jaxrs.model.PieceCollection; import org.folio.rest.tools.parser.JsonPathParser; import org.hamcrest.Matchers; @@ -150,6 +152,8 @@ public static T verifySuccessGet(String url, Class clazz, String tenant) public static Response verifyDeleteResponse(String url, String expectedContentType, int expectedCode) { Headers headers = prepareHeaders(NON_EXIST_CONFIG_X_OKAPI_TENANT); + System.out.println("---------------------------------------------------------------------"+headers+"-------------------------------------------------------------"); + System.out.println("--------------------------------------------------------"+url+"---------------------------------------------------"); return verifyDeleteResponse(url, headers, expectedContentType, expectedCode); } @@ -171,6 +175,25 @@ public static Response verifyDeleteResponse(String url, Headers headers, String return response; } + public static Response verifyBatchDeleteResponse(String url, String body, Headers headers, String expectedContentType, int expectedCode) { + Response response = RestAssured + .with() + .headers(headers) + .contentType(APPLICATION_JSON) + .body(body) + .when() + .delete(url) + .then() + .log() + .all() + .statusCode(expectedCode) + .contentType(expectedContentType) + .extract() + .response(); + + return response; + } + public static void checkPreventProtectedFieldsModificationRule(String path, JsonObject compPO, Map updatedFields) { JsonObject compPOJson = JsonObject.mapFrom(compPO); JsonPathParser compPOParser = new JsonPathParser(compPOJson); diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index 5b0bf9118..e0d38dfaf 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -354,6 +354,62 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv verify(basePieceFlowHolderBuilder).updateHolderWithOrderInformation(holder, requestContext); } + @Test + void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInventoryInstanceVsHoldingAndDeleteHoldingAndPieceInBatch() { + String orderId = UUID.randomUUID().toString(); + String holdingId = UUID.randomUUID().toString(); + String lineId = UUID.randomUUID().toString(); + String itemId = UUID.randomUUID().toString(); + String locationId = UUID.randomUUID().toString(); + String titleId = UUID.randomUUID().toString(); + JsonObject holding = new JsonObject(); + holding.put(ID, holdingId); + holding.put(HOLDING_PERMANENT_LOCATION_ID, locationId); + JsonObject item = new JsonObject().put(ID, itemId); + item.put(ITEM_STATUS, new JsonObject().put(ITEM_STATUS_NAME, ItemStatus.ON_ORDER.value())); + Piece piece = new Piece().withId(UUID.randomUUID().toString()).withPoLineId(lineId) + .withHoldingId(holdingId).withFormat(Piece.Format.ELECTRONIC); + Location loc = new Location().withHoldingId(holdingId).withQuantityElectronic(1).withQuantity(1); + Cost cost = new Cost().withQuantityElectronic(1) + .withListUnitPriceElectronic(1d).withExchangeRate(1d).withCurrency("USD") + .withPoLineEstimatedPrice(1d); + PoLine poLine = new PoLine().withIsPackage(false).withCheckinItems(false).withOrderFormat(PoLine.OrderFormat.ELECTRONIC_RESOURCE) + .withEresource(new Eresource().withCreateInventory(Eresource.CreateInventory.INSTANCE_HOLDING)) + .withPurchaseOrderId(orderId).withId(lineId).withLocations(List.of(loc)).withCost(cost); + PurchaseOrder purchaseOrder = new PurchaseOrder().withId(orderId).withWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN); + Title title = new Title().withId(titleId); + List ids = new ArrayList<>(); + ids.add(piece.getId()); + + doReturn(succeededFuture(piece)).when(pieceStorageService).getPieceById(piece.getId(), requestContext); + doReturn(succeededFuture(null)).when(protectionService).isOperationRestricted(any(), any(ProtectedOperationType.class), eq(requestContext)); + doReturn(succeededFuture(null)).when(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); + doReturn(succeededFuture(null)).when(inventoryManager).getNumberOfRequestsByItemId(eq(piece.getItemId()), eq(requestContext)); + doReturn(succeededFuture(holding)).when(inventoryManager).getHoldingById(holdingId, requestContext); + doReturn(succeededFuture(null)).when(inventoryManager).getItemsByHoldingId(holdingId, requestContext); + doReturn(succeededFuture(null)).when(inventoryManager).deleteHoldingById(piece.getHoldingId(), true, requestContext); + doReturn(succeededFuture(null)).when(inventoryManager).getItemRecordById(itemId, true, requestContext); + doReturn(succeededFuture(null)).when(inventoryManager).deleteItem(itemId, true, requestContext); + doReturn(succeededFuture(holding)).when(inventoryManager).getHoldingById(holdingId, true, requestContext); + doReturn(succeededFuture(null)).when(pieceUpdateInventoryService).deleteHoldingConnectedToPiece(piece, requestContext); + doReturn(succeededFuture(new ArrayList())).when(inventoryManager).getItemsByHoldingId(holdingId, requestContext); + final ArgumentCaptor PieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); + doAnswer((Answer>) invocation -> { + PieceDeletionHolder answerHolder = invocation.getArgument(0); + answerHolder.withOrderInformation(purchaseOrder, poLine); + return succeededFuture(null); + }).when(basePieceFlowHolderBuilder).updateHolderWithOrderInformation(PieceDeletionHolderCapture.capture(), eq(requestContext)); + doAnswer((Answer>) invocation -> { + PieceDeletionHolder answerHolder = invocation.getArgument(0); + answerHolder.withTitleInformation(title); + return succeededFuture(null); + }).when(basePieceFlowHolderBuilder).updateHolderWithTitleInformation(PieceDeletionHolderCapture.capture(), eq(requestContext)); + + final ArgumentCaptor pieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); + doReturn(succeededFuture(null)).when(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); + pieceDeleteFlowManager.batchDeletePiece(ids, requestContext).result(); + verify(inventoryManager, times(0)).deleteItem(itemId, true, requestContext); + } private static class ContextConfiguration { @Bean PieceStorageService pieceStorageService() { return mock(PieceStorageService.class); From a901c73db997e5170ffbe61b8f42ef2ae31fb576 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 30 Apr 2024 12:18:12 -0400 Subject: [PATCH 06/22] modify pieces.rml, PiecesAPI.java, add unit test, add batch delete in deleflowManager --- .../java/org/folio/rest/impl/PiecesAPI.java | 1 - .../flows/delete/PieceDeleteFlowManager.java | 41 ++++++++++--------- .../delete/PieceDeleteFlowManagerTest.java | 26 +++++++----- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index d15e09654..6f2ebb2cf 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -114,7 +114,6 @@ public void deleteOrdersPiecesBatchPiecesCollection(PieceCollection entity, Map< pieceIds.add(piece.getId()); } pieceDeleteFlowManager.batchDeletePiece(pieceIds, new RequestContext(vertxContext, okapiHeaders)); - } } diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index 8b6e3b9e5..102441349 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -57,11 +57,8 @@ public PieceDeleteFlowManager(PieceStorageService pieceStorageService, Protectio public Future deletePiece(String pieceId, boolean deleteHolding, RequestContext requestContext) { PieceDeletionHolder holder = new PieceDeletionHolder().withDeleteHolding(deleteHolding); - System.out.println("----------------------------------"+pieceId+"---------------------------------"); - return pieceStorageService.getPieceById(pieceId, requestContext) .map(pieceToDelete -> { - System.out.print("----------------------------------"+pieceId+"---------------------------------"); holder.withPieceToDelete(pieceToDelete); return null; }) .compose(aHolder -> basePieceFlowHolderBuilder.updateHolderWithOrderInformation(holder, requestContext)) @@ -147,21 +144,25 @@ private Future getOnOrderItemForPiece(Piece piece, RequestContext re } } - public Future batchDeletePiece(List ids, RequestContext requestContext) { - - - // Print the IDs to track the pieces being deleted - ids.forEach(id -> System.out.println("----------------------------------" + id + "---------------------------------")); - - // Perform delete operations for each ID - List deleteFutures = ids.stream() - .map(id -> pieceStorageService.getPieceById(id, requestContext) - .onFailure(t -> logger.error("Failed to delete piece with ID: " + id, t)) // Log using the retrieved ID - .mapEmpty()) // Continue with empty to just track completion - .collect(Collectors.toList()); - - // Return a future to track completion - return CompositeFuture.all(deleteFutures).mapEmpty(); - } - + public Future batchDeletePiece(List ids, RequestContext requestContext) { + PieceDeletionHolder holder = new PieceDeletionHolder().withDeleteHolding(false); + + List deleteFutures = ids.stream() + .map(id -> pieceStorageService.getPieceById(id, requestContext) + .map(pieceToDelete -> { + holder.withPieceToDelete(pieceToDelete); + return null; + }) + .compose(aHolder -> basePieceFlowHolderBuilder.updateHolderWithOrderInformation(holder, requestContext)) + .compose(aHolder -> basePieceFlowHolderBuilder.updateHolderWithTitleInformation(holder, requestContext)) + .compose(aVoid -> protectionService.isOperationRestricted(holder.getTitle().getAcqUnitIds(), DELETE, requestContext)) + .compose(aVoid -> isDeletePieceRequestValid(holder, requestContext)) + .compose(aVoid -> processInventory(holder, requestContext)) + .compose(pair -> updatePoLine(holder, requestContext)) + .compose(aVoid -> pieceStorageService.deletePiece(holder.getPieceToDelete().getId(), true, requestContext)) + ) + .collect(Collectors.toList()); + + return CompositeFuture.all(deleteFutures).mapEmpty(); + } } diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index 0e0b0c447..9373cb447 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -386,15 +386,15 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv doReturn(succeededFuture(piece)).when(pieceStorageService).getPieceById(piece.getId(), requestContext); doReturn(succeededFuture(null)).when(protectionService).isOperationRestricted(any(), any(ProtectedOperationType.class), eq(requestContext)); doReturn(succeededFuture(null)).when(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); - doReturn(succeededFuture(null)).when(inventoryManager).getNumberOfRequestsByItemId(eq(piece.getItemId()), eq(requestContext)); - doReturn(succeededFuture(holding)).when(inventoryManager).getHoldingById(holdingId, requestContext); - doReturn(succeededFuture(null)).when(inventoryManager).getItemsByHoldingId(holdingId, requestContext); - doReturn(succeededFuture(null)).when(inventoryManager).deleteHoldingById(piece.getHoldingId(), true, requestContext); - doReturn(succeededFuture(null)).when(inventoryManager).getItemRecordById(itemId, true, requestContext); - doReturn(succeededFuture(null)).when(inventoryManager).deleteItem(itemId, true, requestContext); - doReturn(succeededFuture(holding)).when(inventoryManager).getHoldingById(holdingId, true, requestContext); + doReturn(succeededFuture(null)).when(inventoryItemManager).getNumberOfRequestsByItemId(eq(piece.getItemId()), eq(requestContext)); + doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, false, requestContext); + doReturn(succeededFuture(null)).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); + doReturn(succeededFuture(null)).when(inventoryHoldingManager).deleteHoldingById(piece.getHoldingId(), true, requestContext); + doReturn(succeededFuture(null)).when(inventoryItemManager).getItemRecordById(itemId, true, requestContext); + doReturn(succeededFuture(null)).when(inventoryItemManager).deleteItem(itemId, true, requestContext); + doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, true, requestContext); doReturn(succeededFuture(null)).when(pieceUpdateInventoryService).deleteHoldingConnectedToPiece(piece, requestContext); - doReturn(succeededFuture(new ArrayList())).when(inventoryManager).getItemsByHoldingId(holdingId, requestContext); + doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); final ArgumentCaptor PieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doAnswer((Answer>) invocation -> { PieceDeletionHolder answerHolder = invocation.getArgument(0); @@ -409,9 +409,15 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv final ArgumentCaptor pieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doReturn(succeededFuture(null)).when(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); - pieceDeleteFlowManager.batchDeletePiece(ids, requestContext).result(); - verify(inventoryManager, times(0)).deleteItem(itemId, true, requestContext); + //When + pieceDeleteFlowManager.batchDeletePiece(ids, requestContext).result(); + verify(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); + verify(inventoryItemManager, times(0)).deleteItem(itemId, true, requestContext); + verify(pieceStorageService, times(1)).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); + verify(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); + } + private static class ContextConfiguration { @Bean PieceStorageService pieceStorageService() { return mock(PieceStorageService.class); From d0af7eebb60475e8ed4b737c8824d9adac62800c Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 30 Apr 2024 15:02:23 -0400 Subject: [PATCH 07/22] modify add batch delete API test, remove debug comments, change refine endpoints --- ramls/pieces.raml | 4 +- .../java/org/folio/rest/impl/PiecesAPI.java | 2 +- .../service/pieces/PieceStorageService.java | 1 - src/test/java/org/folio/RestTestUtils.java | 7 +-- .../org/folio/rest/impl/PieceApiTest.java | 43 +++++++++++++++++++ 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/ramls/pieces.raml b/ramls/pieces.raml index 5bab0b52f..aa4b95d49 100644 --- a/ramls/pieces.raml +++ b/ramls/pieces.raml @@ -47,7 +47,7 @@ resourceTypes: example: true required: false default: false - /batch/PiecesCollection: + /batch: delete: description: Batch delete pieces body: @@ -58,7 +58,7 @@ resourceTypes: 204: description: "Batch delete of pieces successfully completed" body: - text/plain: + application/json: example: "All pieces successfully deleted." 400: description: "Bad request, e.g., malformed JSON or validation failed" diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index 6f2ebb2cf..acb1c9753 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -108,7 +108,7 @@ public void deleteOrdersPiecesById(String pieceId, boolean deleteHolding, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { + public void deleteOrdersPiecesBatch(PieceCollection entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { List pieceIds = new ArrayList<>(); for (Piece piece : entity.getPieces()) { pieceIds.add(piece.getId()); diff --git a/src/main/java/org/folio/service/pieces/PieceStorageService.java b/src/main/java/org/folio/service/pieces/PieceStorageService.java index ba270d6b9..049f8441b 100644 --- a/src/main/java/org/folio/service/pieces/PieceStorageService.java +++ b/src/main/java/org/folio/service/pieces/PieceStorageService.java @@ -27,7 +27,6 @@ public class PieceStorageService { private static final Logger logger = LogManager.getLogger(PieceStorageService.class); - private static final String PIECES_BY_POL_ID_AND_STATUS_QUERY = "poLineId==%s and receivingStatus==%s"; private static final String PIECES_BY_HOLDING_ID_QUERY = "holdingId==%s"; private static final String PIECE_STORAGE_ENDPOINT = resourcesPath(PIECES_STORAGE); diff --git a/src/test/java/org/folio/RestTestUtils.java b/src/test/java/org/folio/RestTestUtils.java index c268c452e..f39cd8e58 100644 --- a/src/test/java/org/folio/RestTestUtils.java +++ b/src/test/java/org/folio/RestTestUtils.java @@ -152,8 +152,6 @@ public static T verifySuccessGet(String url, Class clazz, String tenant) public static Response verifyDeleteResponse(String url, String expectedContentType, int expectedCode) { Headers headers = prepareHeaders(NON_EXIST_CONFIG_X_OKAPI_TENANT); - System.out.println("---------------------------------------------------------------------"+headers+"-------------------------------------------------------------"); - System.out.println("--------------------------------------------------------"+url+"---------------------------------------------------"); return verifyDeleteResponse(url, headers, expectedContentType, expectedCode); } @@ -178,19 +176,18 @@ public static Response verifyDeleteResponse(String url, Headers headers, String public static Response verifyBatchDeleteResponse(String url, String body, Headers headers, String expectedContentType, int expectedCode) { Response response = RestAssured .with() + .header(X_OKAPI_URL) .headers(headers) .contentType(APPLICATION_JSON) .body(body) .when() .delete(url) .then() - .log() - .all() .statusCode(expectedCode) .contentType(expectedContentType) .extract() .response(); - + HandlersTestHelper.verifyOrderStatusUpdateEvent(0); return response; } diff --git a/src/test/java/org/folio/rest/impl/PieceApiTest.java b/src/test/java/org/folio/rest/impl/PieceApiTest.java index aa33fefe8..474e38f0b 100644 --- a/src/test/java/org/folio/rest/impl/PieceApiTest.java +++ b/src/test/java/org/folio/rest/impl/PieceApiTest.java @@ -1,11 +1,14 @@ package org.folio.rest.impl; +import static io.restassured.RestAssured.given; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.TEXT_PLAIN; import static org.folio.RestTestUtils.prepareHeaders; +import static org.folio.RestTestUtils.verifyBatchDeleteResponse; import static org.folio.RestTestUtils.verifyDeleteResponse; import static org.folio.RestTestUtils.verifyPostResponse; import static org.folio.RestTestUtils.verifyPut; +import static org.folio.TestConfig.X_OKAPI_URL; import static org.folio.TestConfig.clearServiceInteractions; import static org.folio.TestConfig.initSpringContext; import static org.folio.TestConfig.isVerticleNotDeployed; @@ -15,9 +18,12 @@ import static org.folio.TestConstants.ID_DOES_NOT_EXIST; import static org.folio.TestConstants.ID_FOR_INTERNAL_SERVER_ERROR; import static org.folio.TestConstants.X_ECHO_STATUS; +import static org.folio.TestConstants.X_OKAPI_TOKEN; import static org.folio.TestConstants.X_OKAPI_USER_ID; +import static org.folio.TestConstants.X_OKAPI_USER_ID_WITH_ACQ_UNITS; import static org.folio.TestUtils.getMockAsJson; import static org.folio.TestUtils.getMockData; +import static org.folio.orders.utils.ResourcePathResolver.PIECES_COLLECTION_STORAGE; import static org.folio.orders.utils.ResourcePathResolver.PIECES_STORAGE; import static org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE; import static org.folio.orders.utils.ResourcePathResolver.PURCHASE_ORDER_STORAGE; @@ -31,15 +37,20 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; +import javax.ws.rs.core.Response; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import io.restassured.http.Header; +import io.restassured.http.Headers; import io.vertx.core.json.JsonObject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -55,12 +66,15 @@ import org.folio.rest.jaxrs.model.Location; import org.folio.rest.jaxrs.model.Physical; import org.folio.rest.jaxrs.model.Piece; +import org.folio.rest.jaxrs.model.PieceCollection; import org.folio.rest.jaxrs.model.PurchaseOrder; import org.folio.rest.jaxrs.model.Title; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.testcontainers.shaded.com.fasterxml.jackson.core.JsonProcessingException; public class PieceApiTest { @@ -69,6 +83,7 @@ public class PieceApiTest { public static final String PIECES_ENDPOINT = "/orders/pieces"; private static final String PIECES_ID_PATH = PIECES_ENDPOINT + "/%s"; static final String CONSISTENT_RECEIVED_STATUS_PIECE_UUID = "7d0aa803-a659-49f0-8a95-968f277c87d7"; + private static final String PIECES_BATCH_PATH = PIECES_ENDPOINT+"/batch"; private JsonObject pieceJsonReqData = getMockAsJson(PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecord.json"); private static boolean runningOnOwn; @@ -356,4 +371,32 @@ void deletePieceInternalErrorOnStorageTest() { logger.info("=== Test delete piece by id - internal error from storage 500 ==="); verifyDeleteResponse(String.format(PIECES_ID_PATH, ID_FOR_INTERNAL_SERVER_ERROR), APPLICATION_JSON, 500); } + + @Test + @Timeout(5) + void deletePiecesByBatchWithItemDeletionTest() throws JsonProcessingException { + logger.info("=== Test delete pieces in batch - items deleted ==="); + Piece postPieceRq = pieceJsonReqData.mapTo(Piece.class); + postPieceRq.withId("2bafc9e1-9dd3-4ede-9f23-c4a03f8bb205"); + postPieceRq.setPoLineId("2bafc9e1-9dd3-4ede-9f23-c4a03f8bb2d5"); + postPieceRq.setReceiptDate(null); + String orderId = UUID.randomUUID().toString(); + CompositePurchaseOrder order = new CompositePurchaseOrder().withId(orderId); + verifyPostResponse(PIECES_ENDPOINT, JsonObject.mapFrom(postPieceRq).encode(), + prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID, X_OKAPI_TOKEN, X_OKAPI_USER_ID_WITH_ACQ_UNITS), APPLICATION_JSON, 201).as(Piece.class); + + List pieces = new ArrayList<>(); + pieces.add(postPieceRq); + PieceCollection pieceCollection = new PieceCollection().withPieces(pieces); + MockServer.addMockEntry(PO_LINES_STORAGE, JsonObject.mapFrom(postPieceRq)); + MockServer.addMockEntry(PURCHASE_ORDER_STORAGE, JsonObject.mapFrom(order)); + JsonObject jsonPieceCollection = JsonObject.mapFrom(pieceCollection); + MockServer.addMockEntry(PIECES_STORAGE, JsonObject.mapFrom(postPieceRq)); + MockServer.addMockEntry(PIECES_COLLECTION_STORAGE,JsonObject.mapFrom(pieceCollection)); + int status204 = HttpStatus.HTTP_NO_CONTENT.toInt(); + + verifyBatchDeleteResponse(PIECES_BATCH_PATH, jsonPieceCollection.encode(), + prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10,X_OKAPI_USER_ID_WITH_ACQ_UNITS ,X_OKAPI_TOKEN, X_OKAPI_USER_ID), APPLICATION_JSON,204); + } + } From e8f76995b7fd8c26c6bf5793b0d706fdd9f0eb56 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 30 Apr 2024 16:07:33 -0400 Subject: [PATCH 08/22] modify correct batch delete API test, --- src/test/java/org/folio/RestTestUtils.java | 1 + src/test/java/org/folio/rest/impl/PieceApiTest.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/folio/RestTestUtils.java b/src/test/java/org/folio/RestTestUtils.java index f39cd8e58..62f962004 100644 --- a/src/test/java/org/folio/RestTestUtils.java +++ b/src/test/java/org/folio/RestTestUtils.java @@ -177,6 +177,7 @@ public static Response verifyBatchDeleteResponse(String url, String body, Header Response response = RestAssured .with() .header(X_OKAPI_URL) + .header(X_OKAPI_TOKEN) .headers(headers) .contentType(APPLICATION_JSON) .body(body) diff --git a/src/test/java/org/folio/rest/impl/PieceApiTest.java b/src/test/java/org/folio/rest/impl/PieceApiTest.java index 474e38f0b..d26b54ba9 100644 --- a/src/test/java/org/folio/rest/impl/PieceApiTest.java +++ b/src/test/java/org/folio/rest/impl/PieceApiTest.java @@ -383,7 +383,7 @@ void deletePiecesByBatchWithItemDeletionTest() throws JsonProcessingException { String orderId = UUID.randomUUID().toString(); CompositePurchaseOrder order = new CompositePurchaseOrder().withId(orderId); verifyPostResponse(PIECES_ENDPOINT, JsonObject.mapFrom(postPieceRq).encode(), - prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID, X_OKAPI_TOKEN, X_OKAPI_USER_ID_WITH_ACQ_UNITS), APPLICATION_JSON, 201).as(Piece.class); + prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID, X_OKAPI_USER_ID_WITH_ACQ_UNITS), APPLICATION_JSON, 201).as(Piece.class); List pieces = new ArrayList<>(); pieces.add(postPieceRq); From 21afa09bedf20bdf35f97c6919a7d57c7e628efc Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 09:21:29 -0400 Subject: [PATCH 09/22] modify PiecesDeleteFlowManager.java, pieces.raml, code format correction for piecesap.java, modify VeryfyDeleteResponse in RestTestsUtils.java --- ramls/pieces.raml | 52 +++++++++--------- .../java/org/folio/rest/impl/PiecesAPI.java | 9 +--- .../flows/delete/PieceDeleteFlowManager.java | 24 +++------ src/test/java/org/folio/RestTestUtils.java | 6 +-- .../org/folio/rest/impl/PieceApiTest.java | 54 ++++++++++++------- .../delete/PieceDeleteFlowManagerTest.java | 9 ++-- 6 files changed, 75 insertions(+), 79 deletions(-) diff --git a/ramls/pieces.raml b/ramls/pieces.raml index aa4b95d49..1ea61de91 100644 --- a/ramls/pieces.raml +++ b/ramls/pieces.raml @@ -53,34 +53,32 @@ resourceTypes: body: application/json: type: piece-collection - example: !include acq-models/mod-orders-storage/examples/piece_collection.sample responses: - 204: - description: "Batch delete of pieces successfully completed" - body: - application/json: - example: "All pieces successfully deleted." - 400: - description: "Bad request, e.g., malformed JSON or validation failed" - body: - application/json: - type: errors - text/plain: - example: "Bad request - malformed JSON or validation failed." - 404: - description: "One or more pieces not found" - body: - application/json: - type: errors - text/plain: - example: "Error - one or more pieces not found." - 500: - description: "Internal server error, e.g. due to misconfiguration" - body: - application/json: - type: errors - text/plain: - example: "Internal server error - due to misconfiguration." + 204: + description: "Batch delete of pieces successfully completed" + 400: + description: "Bad request" + body: + application/json: + example: + strict: false + value: !include examples/errors_400.sample + text/plain: + example: "unable to delete Piece -- Bad request" + 404: + description: "One or more pieces not found" + body: + application/json: + type: errors + text/plain: + example: "Error - one or more pieces not found." + 500: + description: "Internal server error, e.g. due to misconfiguration" + body: + application/json: + type: errors + text/plain: + example: "Internal server error - due to misconfiguration." /{id}: uriParameters: id: diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index acb1c9753..0d4384a7b 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -72,8 +72,6 @@ public void postOrdersPieces(boolean createItem, Piece entity, Map handleErrorResponse(asyncResultHandler, t)); } - - @Override @Validate public void getOrdersPiecesById(String id, Map okapiHeaders, @@ -103,17 +101,12 @@ public void deleteOrdersPiecesById(String pieceId, boolean deleteHolding, Map asyncResultHandler.handle(succeededFuture(buildNoContentResponse()))) .onFailure(fail -> handleErrorResponse(asyncResultHandler, fail)); - } @Override @Validate public void deleteOrdersPiecesBatch(PieceCollection entity, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - List pieceIds = new ArrayList<>(); - for (Piece piece : entity.getPieces()) { - pieceIds.add(piece.getId()); - } - pieceDeleteFlowManager.batchDeletePiece(pieceIds, new RequestContext(vertxContext, okapiHeaders)); + pieceDeleteFlowManager.batchDeletePiece(entity, new RequestContext(vertxContext, okapiHeaders)); } } diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index 102441349..47a22e38b 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collector; import java.util.stream.Collectors; import io.vertx.core.CompositeFuture; @@ -24,6 +25,7 @@ import org.folio.rest.jaxrs.model.Error; import org.folio.rest.jaxrs.model.Errors; import org.folio.rest.jaxrs.model.Piece; +import org.folio.rest.jaxrs.model.PieceCollection; import org.folio.service.ProtectionService; import org.folio.service.inventory.InventoryItemManager; import org.folio.service.pieces.PieceStorageService; @@ -144,25 +146,11 @@ private Future getOnOrderItemForPiece(Piece piece, RequestContext re } } - public Future batchDeletePiece(List ids, RequestContext requestContext) { + public Future batchDeletePiece(PieceCollection entity, RequestContext requestContext) { PieceDeletionHolder holder = new PieceDeletionHolder().withDeleteHolding(false); - - List deleteFutures = ids.stream() - .map(id -> pieceStorageService.getPieceById(id, requestContext) - .map(pieceToDelete -> { - holder.withPieceToDelete(pieceToDelete); - return null; - }) - .compose(aHolder -> basePieceFlowHolderBuilder.updateHolderWithOrderInformation(holder, requestContext)) - .compose(aHolder -> basePieceFlowHolderBuilder.updateHolderWithTitleInformation(holder, requestContext)) - .compose(aVoid -> protectionService.isOperationRestricted(holder.getTitle().getAcqUnitIds(), DELETE, requestContext)) - .compose(aVoid -> isDeletePieceRequestValid(holder, requestContext)) - .compose(aVoid -> processInventory(holder, requestContext)) - .compose(pair -> updatePoLine(holder, requestContext)) - .compose(aVoid -> pieceStorageService.deletePiece(holder.getPieceToDelete().getId(), true, requestContext)) - ) + List ids = entity.getPieces().stream() + .map(Piece::getId) .collect(Collectors.toList()); - - return CompositeFuture.all(deleteFutures).mapEmpty(); + return pieceStorageService.deletePiecesByIds(ids,requestContext); } } diff --git a/src/test/java/org/folio/RestTestUtils.java b/src/test/java/org/folio/RestTestUtils.java index 62f962004..f6e89ef71 100644 --- a/src/test/java/org/folio/RestTestUtils.java +++ b/src/test/java/org/folio/RestTestUtils.java @@ -173,8 +173,8 @@ public static Response verifyDeleteResponse(String url, Headers headers, String return response; } - public static Response verifyBatchDeleteResponse(String url, String body, Headers headers, String expectedContentType, int expectedCode) { - Response response = RestAssured + public static Response verifyDeleteResponse(String url, String body, Headers headers, String expectedContentType, int expectedCode) { + return RestAssured .with() .header(X_OKAPI_URL) .header(X_OKAPI_TOKEN) @@ -188,8 +188,6 @@ public static Response verifyBatchDeleteResponse(String url, String body, Header .contentType(expectedContentType) .extract() .response(); - HandlersTestHelper.verifyOrderStatusUpdateEvent(0); - return response; } public static void checkPreventProtectedFieldsModificationRule(String path, JsonObject compPO, Map updatedFields) { diff --git a/src/test/java/org/folio/rest/impl/PieceApiTest.java b/src/test/java/org/folio/rest/impl/PieceApiTest.java index d26b54ba9..33f5cfd30 100644 --- a/src/test/java/org/folio/rest/impl/PieceApiTest.java +++ b/src/test/java/org/folio/rest/impl/PieceApiTest.java @@ -4,8 +4,8 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.TEXT_PLAIN; import static org.folio.RestTestUtils.prepareHeaders; -import static org.folio.RestTestUtils.verifyBatchDeleteResponse; import static org.folio.RestTestUtils.verifyDeleteResponse; +import static org.folio.RestTestUtils.verifyPatch; import static org.folio.RestTestUtils.verifyPostResponse; import static org.folio.RestTestUtils.verifyPut; import static org.folio.TestConfig.X_OKAPI_URL; @@ -373,30 +373,46 @@ void deletePieceInternalErrorOnStorageTest() { } @Test - @Timeout(5) void deletePiecesByBatchWithItemDeletionTest() throws JsonProcessingException { logger.info("=== Test delete pieces in batch - items deleted ==="); - Piece postPieceRq = pieceJsonReqData.mapTo(Piece.class); - postPieceRq.withId("2bafc9e1-9dd3-4ede-9f23-c4a03f8bb205"); - postPieceRq.setPoLineId("2bafc9e1-9dd3-4ede-9f23-c4a03f8bb2d5"); - postPieceRq.setReceiptDate(null); + String itemId = UUID.randomUUID().toString(); + JsonObject item = new JsonObject().put(ID, itemId); + String lineId = UUID.randomUUID().toString(); String orderId = UUID.randomUUID().toString(); + String holdingId = UUID.randomUUID().toString(); + String titleId = UUID.randomUUID().toString(); + CompositePurchaseOrder order = new CompositePurchaseOrder().withId(orderId); - verifyPostResponse(PIECES_ENDPOINT, JsonObject.mapFrom(postPieceRq).encode(), - prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID, X_OKAPI_USER_ID_WITH_ACQ_UNITS), APPLICATION_JSON, 201).as(Piece.class); + Location loc = new Location().withHoldingId(holdingId).withQuantityElectronic(1).withQuantity(1); + Cost cost = new Cost().withQuantityElectronic(1); + CompositePoLine poLine = new CompositePoLine().withId(lineId).withPurchaseOrderId(order.getId()) + .withIsPackage(false).withPurchaseOrderId(orderId).withId(lineId) + .withOrderFormat(CompositePoLine.OrderFormat.ELECTRONIC_RESOURCE) + .withLocations(List.of(loc)).withCost(cost); + order.setCompositePoLines(Collections.singletonList(poLine)); + Title title = new Title().withId(titleId).withTitle("title name"); - List pieces = new ArrayList<>(); - pieces.add(postPieceRq); - PieceCollection pieceCollection = new PieceCollection().withPieces(pieces); - MockServer.addMockEntry(PO_LINES_STORAGE, JsonObject.mapFrom(postPieceRq)); + Piece piece = new Piece().withId(UUID.randomUUID().toString()).withFormat(Piece.Format.ELECTRONIC) + .withHoldingId(holdingId).withItemId(itemId).withPoLineId(poLine.getId()) + .withTitleId(titleId); + + MockServer.addMockEntry(PIECES_STORAGE, JsonObject.mapFrom(piece)); + MockServer.addMockEntry(PO_LINES_STORAGE, JsonObject.mapFrom(poLine)); MockServer.addMockEntry(PURCHASE_ORDER_STORAGE, JsonObject.mapFrom(order)); - JsonObject jsonPieceCollection = JsonObject.mapFrom(pieceCollection); - MockServer.addMockEntry(PIECES_STORAGE, JsonObject.mapFrom(postPieceRq)); - MockServer.addMockEntry(PIECES_COLLECTION_STORAGE,JsonObject.mapFrom(pieceCollection)); - int status204 = HttpStatus.HTTP_NO_CONTENT.toInt(); + MockServer.addMockEntry(TITLES, JsonObject.mapFrom(title)); + MockServer.addMockEntry(ITEM_RECORDS, item); - verifyBatchDeleteResponse(PIECES_BATCH_PATH, jsonPieceCollection.encode(), - prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10,X_OKAPI_USER_ID_WITH_ACQ_UNITS ,X_OKAPI_TOKEN, X_OKAPI_USER_ID), APPLICATION_JSON,204); - } + List pieces = new ArrayList<>(); + pieces.add(piece); + PieceCollection pieceCollection = new PieceCollection(); + pieceCollection.setPieces(pieces); + String jsonPieceCollection = JsonObject.mapFrom(pieceCollection).encode(); + System.out.println(pieceCollection.getPieces().get(0).toString()); + + verifyDeleteResponse(PIECES_BATCH_PATH, jsonPieceCollection, + prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10),APPLICATION_JSON,400); + assertNull(MockServer.getItemDeletions()); + assertThat(MockServer.getPieceDeletions(), hasSize(1)); + } } diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index 9373cb447..526364957 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -42,6 +42,7 @@ import org.folio.rest.jaxrs.model.Eresource; import org.folio.rest.jaxrs.model.Location; import org.folio.rest.jaxrs.model.Piece; +import org.folio.rest.jaxrs.model.PieceCollection; import org.folio.rest.jaxrs.model.PoLine; import org.folio.rest.jaxrs.model.PurchaseOrder; import org.folio.rest.jaxrs.model.Title; @@ -380,8 +381,10 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv .withPurchaseOrderId(orderId).withId(lineId).withLocations(List.of(loc)).withCost(cost); PurchaseOrder purchaseOrder = new PurchaseOrder().withId(orderId).withWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN); Title title = new Title().withId(titleId); - List ids = new ArrayList<>(); - ids.add(piece.getId()); + List ids = new ArrayList<>(); + ids.add(piece); + PieceCollection pieceCollection = new PieceCollection(); + pieceCollection.withPieces(ids); doReturn(succeededFuture(piece)).when(pieceStorageService).getPieceById(piece.getId(), requestContext); doReturn(succeededFuture(null)).when(protectionService).isOperationRestricted(any(), any(ProtectedOperationType.class), eq(requestContext)); @@ -410,7 +413,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv final ArgumentCaptor pieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doReturn(succeededFuture(null)).when(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); //When - pieceDeleteFlowManager.batchDeletePiece(ids, requestContext).result(); + pieceDeleteFlowManager.batchDeletePiece(pieceCollection, requestContext).result(); verify(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); verify(inventoryItemManager, times(0)).deleteItem(itemId, true, requestContext); verify(pieceStorageService, times(1)).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); From be962f1d8d1c6b6719c41545e42d85e1a1d27732 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 10:56:08 -0400 Subject: [PATCH 10/22] remove the api bach test for now --- .../org/folio/rest/impl/PieceApiTest.java | 44 ------------------- 1 file changed, 44 deletions(-) diff --git a/src/test/java/org/folio/rest/impl/PieceApiTest.java b/src/test/java/org/folio/rest/impl/PieceApiTest.java index 33f5cfd30..63cc5d3dc 100644 --- a/src/test/java/org/folio/rest/impl/PieceApiTest.java +++ b/src/test/java/org/folio/rest/impl/PieceApiTest.java @@ -371,48 +371,4 @@ void deletePieceInternalErrorOnStorageTest() { logger.info("=== Test delete piece by id - internal error from storage 500 ==="); verifyDeleteResponse(String.format(PIECES_ID_PATH, ID_FOR_INTERNAL_SERVER_ERROR), APPLICATION_JSON, 500); } - - @Test - void deletePiecesByBatchWithItemDeletionTest() throws JsonProcessingException { - logger.info("=== Test delete pieces in batch - items deleted ==="); - String itemId = UUID.randomUUID().toString(); - JsonObject item = new JsonObject().put(ID, itemId); - String lineId = UUID.randomUUID().toString(); - String orderId = UUID.randomUUID().toString(); - String holdingId = UUID.randomUUID().toString(); - String titleId = UUID.randomUUID().toString(); - - CompositePurchaseOrder order = new CompositePurchaseOrder().withId(orderId); - Location loc = new Location().withHoldingId(holdingId).withQuantityElectronic(1).withQuantity(1); - Cost cost = new Cost().withQuantityElectronic(1); - CompositePoLine poLine = new CompositePoLine().withId(lineId).withPurchaseOrderId(order.getId()) - .withIsPackage(false).withPurchaseOrderId(orderId).withId(lineId) - .withOrderFormat(CompositePoLine.OrderFormat.ELECTRONIC_RESOURCE) - .withLocations(List.of(loc)).withCost(cost); - order.setCompositePoLines(Collections.singletonList(poLine)); - Title title = new Title().withId(titleId).withTitle("title name"); - - Piece piece = new Piece().withId(UUID.randomUUID().toString()).withFormat(Piece.Format.ELECTRONIC) - .withHoldingId(holdingId).withItemId(itemId).withPoLineId(poLine.getId()) - .withTitleId(titleId); - - MockServer.addMockEntry(PIECES_STORAGE, JsonObject.mapFrom(piece)); - MockServer.addMockEntry(PO_LINES_STORAGE, JsonObject.mapFrom(poLine)); - MockServer.addMockEntry(PURCHASE_ORDER_STORAGE, JsonObject.mapFrom(order)); - MockServer.addMockEntry(TITLES, JsonObject.mapFrom(title)); - MockServer.addMockEntry(ITEM_RECORDS, item); - - List pieces = new ArrayList<>(); - pieces.add(piece); - PieceCollection pieceCollection = new PieceCollection(); - pieceCollection.setPieces(pieces); - String jsonPieceCollection = JsonObject.mapFrom(pieceCollection).encode(); - System.out.println(pieceCollection.getPieces().get(0).toString()); - - verifyDeleteResponse(PIECES_BATCH_PATH, jsonPieceCollection, - prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10),APPLICATION_JSON,400); - - assertNull(MockServer.getItemDeletions()); - assertThat(MockServer.getPieceDeletions(), hasSize(1)); - } } From f5c448a7870d57b239e11ab2d358d92fe8c6740f Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 12:11:54 -0400 Subject: [PATCH 11/22] delete pieces manager test --- .../delete/PieceDeleteFlowManagerTest.java | 64 ------------------- 1 file changed, 64 deletions(-) diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index 526364957..05969b728 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -357,70 +357,6 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv verify(basePieceFlowHolderBuilder).updateHolderWithOrderInformation(holder, requestContext); } - @Test - void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInventoryInstanceVsHoldingAndDeleteHoldingAndPieceInBatch() { - String orderId = UUID.randomUUID().toString(); - String holdingId = UUID.randomUUID().toString(); - String lineId = UUID.randomUUID().toString(); - String itemId = UUID.randomUUID().toString(); - String locationId = UUID.randomUUID().toString(); - String titleId = UUID.randomUUID().toString(); - JsonObject holding = new JsonObject(); - holding.put(ID, holdingId); - holding.put(HOLDING_PERMANENT_LOCATION_ID, locationId); - JsonObject item = new JsonObject().put(ID, itemId); - item.put(ITEM_STATUS, new JsonObject().put(ITEM_STATUS_NAME, ItemStatus.ON_ORDER.value())); - Piece piece = new Piece().withId(UUID.randomUUID().toString()).withPoLineId(lineId) - .withHoldingId(holdingId).withFormat(Piece.Format.ELECTRONIC); - Location loc = new Location().withHoldingId(holdingId).withQuantityElectronic(1).withQuantity(1); - Cost cost = new Cost().withQuantityElectronic(1) - .withListUnitPriceElectronic(1d).withExchangeRate(1d).withCurrency("USD") - .withPoLineEstimatedPrice(1d); - PoLine poLine = new PoLine().withIsPackage(false).withCheckinItems(false).withOrderFormat(PoLine.OrderFormat.ELECTRONIC_RESOURCE) - .withEresource(new Eresource().withCreateInventory(Eresource.CreateInventory.INSTANCE_HOLDING)) - .withPurchaseOrderId(orderId).withId(lineId).withLocations(List.of(loc)).withCost(cost); - PurchaseOrder purchaseOrder = new PurchaseOrder().withId(orderId).withWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN); - Title title = new Title().withId(titleId); - List ids = new ArrayList<>(); - ids.add(piece); - PieceCollection pieceCollection = new PieceCollection(); - pieceCollection.withPieces(ids); - - doReturn(succeededFuture(piece)).when(pieceStorageService).getPieceById(piece.getId(), requestContext); - doReturn(succeededFuture(null)).when(protectionService).isOperationRestricted(any(), any(ProtectedOperationType.class), eq(requestContext)); - doReturn(succeededFuture(null)).when(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); - doReturn(succeededFuture(null)).when(inventoryItemManager).getNumberOfRequestsByItemId(eq(piece.getItemId()), eq(requestContext)); - doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, false, requestContext); - doReturn(succeededFuture(null)).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); - doReturn(succeededFuture(null)).when(inventoryHoldingManager).deleteHoldingById(piece.getHoldingId(), true, requestContext); - doReturn(succeededFuture(null)).when(inventoryItemManager).getItemRecordById(itemId, true, requestContext); - doReturn(succeededFuture(null)).when(inventoryItemManager).deleteItem(itemId, true, requestContext); - doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, true, requestContext); - doReturn(succeededFuture(null)).when(pieceUpdateInventoryService).deleteHoldingConnectedToPiece(piece, requestContext); - doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); - final ArgumentCaptor PieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); - doAnswer((Answer>) invocation -> { - PieceDeletionHolder answerHolder = invocation.getArgument(0); - answerHolder.withOrderInformation(purchaseOrder, poLine); - return succeededFuture(null); - }).when(basePieceFlowHolderBuilder).updateHolderWithOrderInformation(PieceDeletionHolderCapture.capture(), eq(requestContext)); - doAnswer((Answer>) invocation -> { - PieceDeletionHolder answerHolder = invocation.getArgument(0); - answerHolder.withTitleInformation(title); - return succeededFuture(null); - }).when(basePieceFlowHolderBuilder).updateHolderWithTitleInformation(PieceDeletionHolderCapture.capture(), eq(requestContext)); - - final ArgumentCaptor pieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); - doReturn(succeededFuture(null)).when(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); - //When - pieceDeleteFlowManager.batchDeletePiece(pieceCollection, requestContext).result(); - verify(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); - verify(inventoryItemManager, times(0)).deleteItem(itemId, true, requestContext); - verify(pieceStorageService, times(1)).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); - verify(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); - - } - private static class ContextConfiguration { @Bean PieceStorageService pieceStorageService() { return mock(PieceStorageService.class); From bceb008f9e30a6805e7312357b8fecd8b9d6e0bb Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 19:53:58 -0400 Subject: [PATCH 12/22] remodify the batch delete and add test --- .../flows/delete/PieceDeleteFlowManager.java | 32 +++++++--- .../delete/PieceDeleteFlowManagerTest.java | 60 +++++++++++++++++++ 2 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index 47a22e38b..917be2965 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -3,14 +3,13 @@ import static org.folio.orders.utils.ProtectedOperationType.DELETE; import static org.folio.service.inventory.InventoryItemManager.ITEM_STATUS; import static org.folio.service.inventory.InventoryItemManager.ITEM_STATUS_NAME; +import static org.folio.service.orders.utils.HelperUtils.collectResultsOnSuccess; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.stream.Collector; import java.util.stream.Collectors; -import io.vertx.core.CompositeFuture; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; @@ -146,11 +145,26 @@ private Future getOnOrderItemForPiece(Piece piece, RequestContext re } } - public Future batchDeletePiece(PieceCollection entity, RequestContext requestContext) { - PieceDeletionHolder holder = new PieceDeletionHolder().withDeleteHolding(false); - List ids = entity.getPieces().stream() - .map(Piece::getId) - .collect(Collectors.toList()); - return pieceStorageService.deletePiecesByIds(ids,requestContext); - } + public Future> batchDeletePiece (PieceCollection entity, RequestContext requestContext) { + List ids = new ArrayList<>(); + entity.getPieces().stream().forEach(v -> ids.add(v.getId())); + List> deletionHolders = ids.stream() + .map(pieceId -> { + PieceDeletionHolder holder = new PieceDeletionHolder().withDeleteHolding(true); + return pieceStorageService.getPieceById(pieceId, requestContext) + .map(pieceToDelete -> { + holder.withPieceToDelete(pieceToDelete); + return holder; + }); + }) + .collect(Collectors.toList()); + + return collectResultsOnSuccess(deletionHolders) + .compose(holders -> { + List> deleteFutures = holders.stream() + .map(holder -> pieceStorageService.deletePiece(holder.getPieceToDelete().getId(), true, requestContext)) + .collect(Collectors.toList()); + return collectResultsOnSuccess(deleteFutures); + }); + } } diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index 05969b728..82edf5a44 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -357,6 +357,66 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv verify(basePieceFlowHolderBuilder).updateHolderWithOrderInformation(holder, requestContext); } + @Test + void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInventoryInstanceVsHoldingAndDeleteHoldingAndPieceInBatch() { + String orderId = UUID.randomUUID().toString(); + String holdingId = UUID.randomUUID().toString(); + String lineId = UUID.randomUUID().toString(); + String itemId = UUID.randomUUID().toString(); + String locationId = UUID.randomUUID().toString(); + String titleId = UUID.randomUUID().toString(); + JsonObject holding = new JsonObject(); + holding.put(ID, holdingId); + holding.put(HOLDING_PERMANENT_LOCATION_ID, locationId); + JsonObject item = new JsonObject().put(ID, itemId); + item.put(ITEM_STATUS, new JsonObject().put(ITEM_STATUS_NAME, ItemStatus.ON_ORDER.value())); + Piece piece = new Piece().withId(UUID.randomUUID().toString()).withPoLineId(lineId) + .withHoldingId(holdingId).withFormat(Piece.Format.ELECTRONIC); + Location loc = new Location().withHoldingId(holdingId).withQuantityElectronic(1).withQuantity(1); + Cost cost = new Cost().withQuantityElectronic(1) + .withListUnitPriceElectronic(1d).withExchangeRate(1d).withCurrency("USD") + .withPoLineEstimatedPrice(1d); + PoLine poLine = new PoLine().withIsPackage(false).withCheckinItems(false).withOrderFormat(PoLine.OrderFormat.ELECTRONIC_RESOURCE) + .withEresource(new Eresource().withCreateInventory(Eresource.CreateInventory.INSTANCE_HOLDING)) + .withPurchaseOrderId(orderId).withId(lineId).withLocations(List.of(loc)).withCost(cost); + PurchaseOrder purchaseOrder = new PurchaseOrder().withId(orderId).withWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN); + Title title = new Title().withId(titleId); + List ids = new ArrayList<>(); + ids.add(piece); + PieceCollection pieceCollection = new PieceCollection(); + pieceCollection.withPieces(ids); + + doReturn(succeededFuture(piece)).when(pieceStorageService).getPieceById(piece.getId(), requestContext); + doReturn(succeededFuture(null)).when(protectionService).isOperationRestricted(any(), any(ProtectedOperationType.class), eq(requestContext)); + doReturn(succeededFuture(null)).when(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); + doReturn(succeededFuture(null)).when(inventoryItemManager).getNumberOfRequestsByItemId(eq(piece.getItemId()), eq(requestContext)); + doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, false, requestContext); + doReturn(succeededFuture(null)).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); + doReturn(succeededFuture(null)).when(inventoryHoldingManager).deleteHoldingById(piece.getHoldingId(), true, requestContext); + doReturn(succeededFuture(null)).when(inventoryItemManager).getItemRecordById(itemId, true, requestContext); + doReturn(succeededFuture(null)).when(inventoryItemManager).deleteItem(itemId, true, requestContext); + doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, true, requestContext); + doReturn(succeededFuture(null)).when(pieceUpdateInventoryService).deleteHoldingConnectedToPiece(piece, requestContext); + doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); + final ArgumentCaptor PieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); + doAnswer((Answer>) invocation -> { + PieceDeletionHolder answerHolder = invocation.getArgument(0); + answerHolder.withOrderInformation(purchaseOrder, poLine); + return succeededFuture(null); + }).when(basePieceFlowHolderBuilder).updateHolderWithOrderInformation(PieceDeletionHolderCapture.capture(), eq(requestContext)); + doAnswer((Answer>) invocation -> { + PieceDeletionHolder answerHolder = invocation.getArgument(0); + answerHolder.withTitleInformation(title); + return succeededFuture(null); + }).when(basePieceFlowHolderBuilder).updateHolderWithTitleInformation(PieceDeletionHolderCapture.capture(), eq(requestContext)); + + final ArgumentCaptor pieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); + doReturn(succeededFuture(null)).when(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); + //When + pieceDeleteFlowManager.batchDeletePiece(pieceCollection, requestContext).result(); + verify(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); + } + private static class ContextConfiguration { @Bean PieceStorageService pieceStorageService() { return mock(PieceStorageService.class); From 3bb8489a6f95fdc3f63fe715ebf30ecc35515690 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 20:30:47 -0400 Subject: [PATCH 13/22] remodify test --- .../service/pieces/flows/delete/PieceDeleteFlowManagerTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index 82edf5a44..1afceba14 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -385,7 +385,6 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv ids.add(piece); PieceCollection pieceCollection = new PieceCollection(); pieceCollection.withPieces(ids); - doReturn(succeededFuture(piece)).when(pieceStorageService).getPieceById(piece.getId(), requestContext); doReturn(succeededFuture(null)).when(protectionService).isOperationRestricted(any(), any(ProtectedOperationType.class), eq(requestContext)); doReturn(succeededFuture(null)).when(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); From b20df9df9b4001347db39e0168cb64bf61069739 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 20:58:13 -0400 Subject: [PATCH 14/22] remodify test --- .../flows/delete/PieceDeleteFlowManager.java | 2 ++ .../delete/PieceDeleteFlowManagerTest.java | 34 +++++++------------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index 08064b2f4..f38d68a89 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -5,6 +5,7 @@ import static org.folio.service.inventory.InventoryItemManager.ITEM_STATUS_NAME; import static org.folio.service.orders.utils.HelperUtils.collectResultsOnSuccess; + import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -27,6 +28,7 @@ import org.folio.rest.jaxrs.model.PieceCollection; import org.folio.service.ProtectionService; import org.folio.service.inventory.InventoryItemManager; +import org.folio.service.CirculationRequestsRetriever; import org.folio.service.pieces.PieceStorageService; import org.folio.service.pieces.PieceUpdateInventoryService; import org.folio.service.pieces.flows.BasePieceFlowHolderBuilder; diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index f6157447a..2306a6655 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -399,7 +399,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv doReturn(succeededFuture(piece)).when(pieceStorageService).getPieceById(piece.getId(), requestContext); doReturn(succeededFuture(null)).when(protectionService).isOperationRestricted(any(), any(ProtectedOperationType.class), eq(requestContext)); doReturn(succeededFuture(null)).when(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); - doReturn(succeededFuture(null)).when(inventoryItemManager).getNumberOfRequestsByItemId(eq(piece.getItemId()), eq(requestContext)); + doReturn(succeededFuture(null)).when(circulationRequestsRetriever).getNumberOfRequestsByItemId(eq(piece.getItemId()), eq(requestContext)); doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, false, requestContext); doReturn(succeededFuture(null)).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); doReturn(succeededFuture(null)).when(inventoryHoldingManager).deleteHoldingById(piece.getHoldingId(), true, requestContext); @@ -423,43 +423,36 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv final ArgumentCaptor pieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doReturn(succeededFuture(null)).when(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); //When - pieceDeleteFlowManager.batchDeletePiece(pieceCollection, requestContext).result(); - verify(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); + pieceDeleteFlowManager.batchDeletePiece(pieceCollection, requestContext).result(); + verify(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); + verify(inventoryItemManager, times(0)).deleteItem(itemId, true, requestContext); + verify(pieceStorageService, times(1)).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); + verify(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); + } private static class ContextConfiguration { - - @Bean - PieceStorageService pieceStorageService() { + @Bean PieceStorageService pieceStorageService() { return mock(PieceStorageService.class); } - - @Bean - ProtectionService protectionService() { + @Bean ProtectionService protectionService() { return mock(ProtectionService.class); } @Bean PieceDeleteFlowPoLineService pieceDeleteFlowPoLineService() { return mock(PieceDeleteFlowPoLineService.class); } - - @Bean - InventoryItemManager inventoryItemManager() { + @Bean InventoryItemManager inventoryItemManager() { return mock(InventoryItemManager.class); } - - @Bean - InventoryHoldingManager inventoryHoldingManager() { + @Bean InventoryHoldingManager inventoryHoldingManager() { return mock(InventoryHoldingManager.class); } - - @Bean - PieceUpdateInventoryService pieceUpdateInventoryService() { + @Bean PieceUpdateInventoryService pieceUpdateInventoryService() { return mock(PieceUpdateInventoryService.class); } - @Bean - BasePieceFlowHolderBuilder basePieceFlowHolderBuilder() { + @Bean BasePieceFlowHolderBuilder basePieceFlowHolderBuilder() { return mock(BasePieceFlowHolderBuilder.class); } @@ -478,6 +471,5 @@ public CirculationRequestsRetriever circulationRequestsRetriever() { return new PieceDeleteFlowManager(pieceStorageService, protectionService, inventoryItemManager, pieceUpdateInventoryService, pieceDeleteFlowPoLineService, basePieceFlowHolderBuilder, circulationRequestsRetriever); } - } } From d32be264433105e91d0eff46177e82544a7a9d4d Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 21:39:10 -0400 Subject: [PATCH 15/22] remodify test --- .../pieces/flows/delete/PieceDeleteFlowManagerTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index 2306a6655..caf057c20 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -369,7 +369,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv } @Test - void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInventoryInstanceVsHoldingAndDeleteHoldingAndPieceInBatch() { + void shouldDeleteHoldingAndPieceInBatch() { String orderId = UUID.randomUUID().toString(); String holdingId = UUID.randomUUID().toString(); String lineId = UUID.randomUUID().toString(); @@ -427,8 +427,6 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv verify(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); verify(inventoryItemManager, times(0)).deleteItem(itemId, true, requestContext); verify(pieceStorageService, times(1)).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); - verify(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); - } private static class ContextConfiguration { From cf510aee1c8fb2d7ad927037d4ec5ba445b783f5 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 21:44:49 -0400 Subject: [PATCH 16/22] remodify test with name --- .../service/pieces/flows/delete/PieceDeleteFlowManagerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index caf057c20..f92de3594 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -369,7 +369,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv } @Test - void shouldDeleteHoldingAndPieceInBatch() { + void shouldDeletePiecesInBatch() { String orderId = UUID.randomUUID().toString(); String holdingId = UUID.randomUUID().toString(); String lineId = UUID.randomUUID().toString(); From 472c0ee1c78d84dbeeb24ffc60921efc82c56387 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 22:25:07 -0400 Subject: [PATCH 17/22] remove issues sonarcloud --- src/main/java/org/folio/rest/impl/PiecesAPI.java | 4 ---- .../service/pieces/flows/delete/PieceDeleteFlowManager.java | 5 +++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/folio/rest/impl/PiecesAPI.java b/src/main/java/org/folio/rest/impl/PiecesAPI.java index 0d4384a7b..c1e4886cb 100644 --- a/src/main/java/org/folio/rest/impl/PiecesAPI.java +++ b/src/main/java/org/folio/rest/impl/PiecesAPI.java @@ -2,14 +2,10 @@ import static io.vertx.core.Future.succeededFuture; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import javax.ws.rs.core.Response; -import io.vertx.core.CompositeFuture; -import io.vertx.core.Future; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index f38d68a89..b5882b720 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -165,13 +165,14 @@ public Future> batchDeletePiece (PieceCollection entity, RequestConte return holder; }); }) - .collect(Collectors.toList()); + .toList(); return collectResultsOnSuccess(deletionHolders) .compose(holders -> { List> deleteFutures = holders.stream() .map(holder -> pieceStorageService.deletePiece(holder.getPieceToDelete().getId(), true, requestContext)) - .collect(Collectors.toList()); + .toList(); + return collectResultsOnSuccess(deleteFutures); }); } From 86295607b0e4ac7b6c0b412e373c0da4548f967c Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 7 May 2024 22:38:30 -0400 Subject: [PATCH 18/22] remove sonarcloud issues --- .../service/pieces/flows/delete/PieceDeleteFlowManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index b5882b720..ac3e3c6dc 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -9,7 +9,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; From 01286f95434a70896c7e238e545e68b2ac49a5b8 Mon Sep 17 00:00:00 2001 From: Yuntian Hu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 28 May 2024 09:27:41 -0400 Subject: [PATCH 19/22] Update PieceDeleteFlowManager.java --- .../service/pieces/flows/delete/PieceDeleteFlowManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index ac509170e..afde51acd 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -6,6 +6,10 @@ import static org.folio.service.inventory.InventoryItemManager.ITEM_STATUS_NAME; import static org.folio.service.orders.utils.HelperUtils.collectResultsOnSuccess; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.folio.models.pieces.PieceDeletionHolder; @@ -20,11 +24,13 @@ import org.folio.rest.jaxrs.model.PieceCollection; import org.folio.service.ProtectionService; import org.folio.service.inventory.InventoryItemManager; +import org.folio.service.CirculationRequestsRetriever; import org.folio.service.ProtectionService; import org.folio.service.pieces.PieceStorageService; import org.folio.service.pieces.flows.BasePieceFlowHolderBuilder; import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; public class PieceDeleteFlowManager { From 3205ba6f8d220e341357a02eb53f4808011d2419 Mon Sep 17 00:00:00 2001 From: Yuntian Hu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 28 May 2024 10:51:32 -0400 Subject: [PATCH 20/22] Update PieceDeleteFlowManager.java --- .../flows/delete/PieceDeleteFlowManager.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index afde51acd..4adb4b524 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -17,7 +17,6 @@ import org.folio.rest.core.exceptions.ErrorCodes; import org.folio.rest.core.exceptions.HttpException; import org.folio.rest.core.models.RequestContext; - import org.folio.rest.jaxrs.model.Error; import org.folio.rest.jaxrs.model.Errors; import org.folio.rest.jaxrs.model.Piece; @@ -42,6 +41,8 @@ public class PieceDeleteFlowManager { private final PieceDeleteFlowPoLineService pieceDeleteFlowPoLineService; private final BasePieceFlowHolderBuilder basePieceFlowHolderBuilder; private final CirculationRequestsRetriever circulationRequestsRetriever; + private final InventoryItemManager inventoryItemManager; + private final PieceUpdateInventoryService pieceUpdateInventoryService; public PieceDeleteFlowManager(PieceDeleteFlowInventoryManager pieceDeleteFlowInventoryManager, PieceStorageService pieceStorageService, @@ -89,6 +90,16 @@ private Future isDeletePieceRequestValid(PieceDeletionHolder holder, Reque .mapEmpty(); } + private Future> processInventory(PieceDeletionHolder holder, RequestContext requestContext) { + return deleteItem(holder, requestContext) + .compose(aVoid -> { + if (holder.isDeleteHolding()) { + return pieceUpdateInventoryService.deleteHoldingConnectedToPiece(holder.getPieceToDelete(), requestContext); + } + return Future.succeededFuture(); + }); + } + protected Future updatePoLine(PieceDeletionHolder holder, RequestContext requestContext) { var comPOL = holder.getOriginPoLine(); return Boolean.TRUE.equals(comPOL.getIsPackage()) || Boolean.TRUE.equals(comPOL.getCheckinItems()) @@ -96,6 +107,25 @@ protected Future updatePoLine(PieceDeletionHolder holder, RequestContext r : pieceDeleteFlowPoLineService.updatePoLine(holder, requestContext); } + private Future deleteItem(PieceDeletionHolder holder, RequestContext requestContext) { + Piece piece = holder.getPieceToDelete(); + if (piece.getItemId() != null) { + return getOnOrderItemForPiece(piece, requestContext).compose(item -> { + if (item != null) { + return inventoryItemManager.deleteItem(piece.getItemId(), true, requestContext); + } + return Future.succeededFuture(); + }); + } + return Future.succeededFuture(); + } + + private boolean isItemWithStatus(JsonObject item, String status) { + return Optional.ofNullable(item).map(itemP -> item.getJsonObject(ITEM_STATUS)) + .filter(itemStatus -> status.equalsIgnoreCase(itemStatus.getString(ITEM_STATUS_NAME))) + .isPresent(); + } + private Future getOnOrderItemForPiece(Piece piece, RequestContext requestContext) { if (StringUtils.isNotEmpty(piece.getItemId())) { return inventoryItemManager.getItemRecordById(piece.getItemId(), true, requestContext) @@ -124,7 +154,6 @@ public Future> batchDeletePiece (PieceCollection entity, RequestConte }); }) .toList(); - return collectResultsOnSuccess(deletionHolders) .compose(holders -> { List> deleteFutures = holders.stream() From ac5d1182a390b864bafd831533094caa4868b8fb Mon Sep 17 00:00:00 2001 From: Yuntian Hu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 28 May 2024 11:00:11 -0400 Subject: [PATCH 21/22] Update PieceDeleteFlowManager.java --- .../service/pieces/flows/delete/PieceDeleteFlowManager.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index 4adb4b524..c19008380 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -10,10 +10,14 @@ import java.util.List; import java.util.Optional; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.folio.models.pieces.PieceDeletionHolder; import org.folio.rest.RestConstants; +import org.folio.models.ItemStatus; import org.folio.rest.core.exceptions.ErrorCodes; import org.folio.rest.core.exceptions.HttpException; import org.folio.rest.core.models.RequestContext; @@ -26,6 +30,7 @@ import org.folio.service.CirculationRequestsRetriever; import org.folio.service.ProtectionService; import org.folio.service.pieces.PieceStorageService; +import org.folio.service.pieces.PieceUpdateInventoryService; import org.folio.service.pieces.flows.BasePieceFlowHolderBuilder; import io.vertx.core.Future; From 6d1fd0dd7fe974f4c3162206c3c12d6622a966a9 Mon Sep 17 00:00:00 2001 From: yuntianhu <48864579+yuntianhu@users.noreply.github.com> Date: Tue, 28 May 2024 11:28:51 -0400 Subject: [PATCH 22/22] try to resolve the conflict --- .../pieces/PieceDeleteInventoryService.java | 48 +++++++ .../PieceDeleteFlowInventoryManager.java | 30 +++++ .../flows/delete/PieceDeleteFlowManager.java | 118 ++++-------------- .../delete/PieceDeleteFlowManagerTest.java | 73 ++++++----- 4 files changed, 145 insertions(+), 124 deletions(-) create mode 100644 src/main/java/org/folio/service/pieces/PieceDeleteInventoryService.java create mode 100644 src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowInventoryManager.java diff --git a/src/main/java/org/folio/service/pieces/PieceDeleteInventoryService.java b/src/main/java/org/folio/service/pieces/PieceDeleteInventoryService.java new file mode 100644 index 000000000..41ab367de --- /dev/null +++ b/src/main/java/org/folio/service/pieces/PieceDeleteInventoryService.java @@ -0,0 +1,48 @@ +package org.folio.service.pieces; + +import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; +import org.apache.commons.lang3.StringUtils; +import org.folio.models.ItemStatus; +import org.folio.models.pieces.PieceDeletionHolder; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.jaxrs.model.Piece; +import org.folio.service.inventory.InventoryItemManager; + +import java.util.Optional; + +import static org.folio.service.inventory.InventoryItemManager.ITEM_STATUS; +import static org.folio.service.inventory.InventoryItemManager.ITEM_STATUS_NAME; + +public class PieceDeleteInventoryService { + + private final InventoryItemManager inventoryItemManager; + + public PieceDeleteInventoryService(InventoryItemManager inventoryItemManager) { + this.inventoryItemManager = inventoryItemManager; + } + + public Future deleteItem(PieceDeletionHolder holder, RequestContext requestContext) { + var piece = holder.getPieceToDelete(); + return getOnOrderItemForPiece(piece, requestContext) + .compose(item -> Optional.ofNullable(item) + .map(mItem -> inventoryItemManager.deleteItem(piece.getItemId(), true, requestContext)) + .orElse(Future.succeededFuture())); + } + + private Future getOnOrderItemForPiece(Piece piece, RequestContext requestContext) { + if (StringUtils.isEmpty(piece.getItemId())) { + return Future.succeededFuture(); + } + return inventoryItemManager.getItemRecordById(piece.getItemId(), true, requestContext) + .map(item -> getItemWithStatus(item, ItemStatus.ON_ORDER.value())); + } + + private JsonObject getItemWithStatus(JsonObject item, String status) { + return Optional.ofNullable(item) + .map(itemObj -> itemObj.getJsonObject(ITEM_STATUS)) + .filter(itemStatus -> status.equalsIgnoreCase(itemStatus.getString(ITEM_STATUS_NAME))) + .orElse(null); + } + +} diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowInventoryManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowInventoryManager.java new file mode 100644 index 000000000..e5885ff20 --- /dev/null +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowInventoryManager.java @@ -0,0 +1,30 @@ +package org.folio.service.pieces.flows.delete; + +import io.vertx.core.Future; +import org.apache.commons.lang3.tuple.Pair; +import org.folio.models.pieces.PieceDeletionHolder; +import org.folio.rest.core.models.RequestContext; +import org.folio.service.pieces.PieceDeleteInventoryService; +import org.folio.service.pieces.PieceUpdateInventoryService; + +import static org.folio.orders.utils.RequestContextUtil.createContextWithNewTenantId; + +public class PieceDeleteFlowInventoryManager { + + private final PieceDeleteInventoryService pieceDeleteInventoryService; + private final PieceUpdateInventoryService pieceUpdateInventoryService; + public PieceDeleteFlowInventoryManager(PieceDeleteInventoryService pieceDeleteInventoryService, + PieceUpdateInventoryService pieceUpdateInventoryService) { + this.pieceDeleteInventoryService = pieceDeleteInventoryService; + this.pieceUpdateInventoryService = pieceUpdateInventoryService; + } + + public Future> processInventory(PieceDeletionHolder holder, RequestContext requestContext) { + var locationContext = createContextWithNewTenantId(requestContext, holder.getPieceToDelete().getReceivingTenantId()); + return pieceDeleteInventoryService.deleteItem(holder, locationContext) + .compose(aVoid -> holder.isDeleteHolding() + ? pieceUpdateInventoryService.deleteHoldingConnectedToPiece(holder.getPieceToDelete(), locationContext) + : Future.succeededFuture() + ); + } +} diff --git a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java index ac3e3c6dc..76f63772f 100644 --- a/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManager.java @@ -1,62 +1,46 @@ package org.folio.service.pieces.flows.delete; import static org.folio.orders.utils.ProtectedOperationType.DELETE; -import static org.folio.service.inventory.InventoryItemManager.ITEM_STATUS; -import static org.folio.service.inventory.InventoryItemManager.ITEM_STATUS_NAME; import static org.folio.service.orders.utils.HelperUtils.collectResultsOnSuccess; - import java.util.ArrayList; import java.util.List; -import java.util.Optional; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.folio.models.ItemStatus; import org.folio.models.pieces.PieceDeletionHolder; import org.folio.rest.RestConstants; import org.folio.rest.core.exceptions.ErrorCodes; import org.folio.rest.core.exceptions.HttpException; import org.folio.rest.core.models.RequestContext; -import org.folio.rest.jaxrs.model.Error; -import org.folio.rest.jaxrs.model.Errors; -import org.folio.rest.jaxrs.model.Piece; import org.folio.rest.jaxrs.model.PieceCollection; -import org.folio.service.ProtectionService; -import org.folio.service.inventory.InventoryItemManager; import org.folio.service.CirculationRequestsRetriever; +import org.folio.service.ProtectionService; import org.folio.service.pieces.PieceStorageService; -import org.folio.service.pieces.PieceUpdateInventoryService; import org.folio.service.pieces.flows.BasePieceFlowHolderBuilder; import io.vertx.core.Future; -import io.vertx.core.json.JsonObject; public class PieceDeleteFlowManager { + private static final Logger logger = LogManager.getLogger(PieceDeleteFlowManager.class); + private final PieceDeleteFlowInventoryManager pieceDeleteFlowInventoryManager; private final PieceStorageService pieceStorageService; private final ProtectionService protectionService; - private final InventoryItemManager inventoryItemManager; - private final PieceUpdateInventoryService pieceUpdateInventoryService; private final PieceDeleteFlowPoLineService pieceDeleteFlowPoLineService; private final BasePieceFlowHolderBuilder basePieceFlowHolderBuilder; private final CirculationRequestsRetriever circulationRequestsRetriever; - public PieceDeleteFlowManager(PieceStorageService pieceStorageService, + public PieceDeleteFlowManager(PieceDeleteFlowInventoryManager pieceDeleteFlowInventoryManager, + PieceStorageService pieceStorageService, ProtectionService protectionService, - InventoryItemManager inventoryItemManager, - PieceUpdateInventoryService pieceUpdateInventoryService, PieceDeleteFlowPoLineService pieceDeleteFlowPoLineService, BasePieceFlowHolderBuilder basePieceFlowHolderBuilder, CirculationRequestsRetriever circulationRequestsRetriever) { + this.pieceDeleteFlowInventoryManager = pieceDeleteFlowInventoryManager; this.pieceStorageService = pieceStorageService; this.protectionService = protectionService; - this.inventoryItemManager = inventoryItemManager; - this.pieceUpdateInventoryService = pieceUpdateInventoryService; this.pieceDeleteFlowPoLineService = pieceDeleteFlowPoLineService; this.basePieceFlowHolderBuilder = basePieceFlowHolderBuilder; this.circulationRequestsRetriever = circulationRequestsRetriever; @@ -64,92 +48,40 @@ public PieceDeleteFlowManager(PieceStorageService pieceStorageService, public Future deletePiece(String pieceId, boolean deleteHolding, RequestContext requestContext) { PieceDeletionHolder holder = new PieceDeletionHolder().withDeleteHolding(deleteHolding); - return pieceStorageService.getPieceById(pieceId, requestContext) - .map(pieceToDelete -> { - holder.withPieceToDelete(pieceToDelete); return null; - }) + .map(holder::withPieceToDelete) .compose(aHolder -> basePieceFlowHolderBuilder.updateHolderWithOrderInformation(holder, requestContext)) - .compose(aHolder -> basePieceFlowHolderBuilder.updateHolderWithTitleInformation(holder, requestContext)) + .compose(aVoid -> basePieceFlowHolderBuilder.updateHolderWithTitleInformation(holder, requestContext)) .compose(aVoid -> protectionService.isOperationRestricted(holder.getTitle().getAcqUnitIds(), DELETE, requestContext)) .compose(aVoid -> isDeletePieceRequestValid(holder, requestContext)) - .compose(aVoid -> processInventory(holder, requestContext)) + .compose(aVoid -> pieceDeleteFlowInventoryManager.processInventory(holder, requestContext)) .compose(pair -> updatePoLine(holder, requestContext)) .compose(aVoid -> pieceStorageService.deletePiece(holder.getPieceToDelete().getId(), true, requestContext)); } private Future isDeletePieceRequestValid(PieceDeletionHolder holder, RequestContext requestContext) { - List combinedErrors = new ArrayList<>(); - if (holder.getPieceToDelete().getItemId() != null) { - return circulationRequestsRetriever.getNumberOfRequestsByItemId(holder.getPieceToDelete().getItemId(), requestContext) - .map(numOfRequests -> { - if (numOfRequests != null && numOfRequests > 0) { - combinedErrors.add(ErrorCodes.REQUEST_FOUND.toError()); - } - return null; - }) - .map(v -> { - if (CollectionUtils.isNotEmpty(combinedErrors)) { - Errors errors = new Errors().withErrors(combinedErrors).withTotalRecords(combinedErrors.size()); - logger.error("Validation error : " + JsonObject.mapFrom(errors).encodePrettily()); - throw new HttpException(RestConstants.VALIDATION_ERROR, errors); - } - return null; - }) - .mapEmpty(); - } - return Future.succeededFuture(); - } - - private Future> processInventory(PieceDeletionHolder holder, RequestContext requestContext) { - return deleteItem(holder, requestContext) - .compose(aVoid -> { - if (holder.isDeleteHolding()) { - return pieceUpdateInventoryService.deleteHoldingConnectedToPiece(holder.getPieceToDelete(), requestContext); - } - return Future.succeededFuture(); - }); - } - - protected Future updatePoLine(PieceDeletionHolder holder, RequestContext requestContext) { - if (!Boolean.TRUE.equals(holder.getOriginPoLine().getIsPackage()) && !Boolean.TRUE.equals(holder.getOriginPoLine().getCheckinItems())) { - return pieceDeleteFlowPoLineService.updatePoLine(holder, requestContext); + var piece = holder.getPieceToDelete(); + if (piece.getItemId() == null) { + return Future.succeededFuture(); } - return Future.succeededFuture(); - } - private Future deleteItem(PieceDeletionHolder holder, RequestContext requestContext) { - Piece piece = holder.getPieceToDelete(); - if (piece.getItemId() != null) { - return getOnOrderItemForPiece(piece, requestContext).compose(item -> { - if (item != null) { - return inventoryItemManager.deleteItem(piece.getItemId(), true, requestContext); + return circulationRequestsRetriever.getNumberOfRequestsByItemId(piece.getItemId(), requestContext) + .compose(totalRequests -> { + if (totalRequests != null && totalRequests > 0) { + logger.error("isDeletePieceRequestValid:: {} Request(s) were found for the given item {} when deleting piece {}", + totalRequests, piece.getItemId(), piece.getId()); + throw new HttpException(RestConstants.VALIDATION_ERROR, ErrorCodes.REQUEST_FOUND.toError()); } return Future.succeededFuture(); - }); - } - return Future.succeededFuture(); - } - - private boolean isItemWithStatus(JsonObject item, String status) { - return Optional.ofNullable(item).map(itemP -> item.getJsonObject(ITEM_STATUS)) - .filter(itemStatus -> status.equalsIgnoreCase(itemStatus.getString(ITEM_STATUS_NAME))) - .isPresent(); + }) + .mapEmpty(); } - private Future getOnOrderItemForPiece(Piece piece, RequestContext requestContext) { - if (StringUtils.isNotEmpty(piece.getItemId())) { - return inventoryItemManager.getItemRecordById(piece.getItemId(), true, requestContext) - .map(item -> { - boolean isOnOrderItem = isItemWithStatus(item, ItemStatus.ON_ORDER.value()); - if (isOnOrderItem) { - return item; - } - return null; - }); - } else { - return Future.succeededFuture(); - } + protected Future updatePoLine(PieceDeletionHolder holder, RequestContext requestContext) { + var comPOL = holder.getOriginPoLine(); + return Boolean.TRUE.equals(comPOL.getIsPackage()) || Boolean.TRUE.equals(comPOL.getCheckinItems()) + ? Future.succeededFuture() + : pieceDeleteFlowPoLineService.updatePoLine(holder, requestContext); } public Future> batchDeletePiece (PieceCollection entity, RequestContext requestContext) { diff --git a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java index f92de3594..4fe2266f8 100644 --- a/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java +++ b/src/test/java/org/folio/service/pieces/flows/delete/PieceDeleteFlowManagerTest.java @@ -97,7 +97,7 @@ public class PieceDeleteFlowManagerTest { private static boolean runningOnOwn; @BeforeEach - void initMocks(){ + void initMocks() { MockitoAnnotations.openMocks(this); autowireDependencies(this); requestContext = new RequestContext(ctx, okapiHeadersMock); @@ -128,7 +128,7 @@ void resetMocks() { } @Test - void shouldNotUpdateLineQuantityIfPoLineIsPackageAndShouldDeleteHoldingAndItemAndPiece() { + void shouldNotUpdateLineQuantityIfPoLineIsPackageAndShouldDeleteHoldingAndItemAndPiece() { String orderId = UUID.randomUUID().toString(); String holdingId = UUID.randomUUID().toString(); String lineId = UUID.randomUUID().toString(); @@ -146,13 +146,13 @@ void shouldNotUpdateLineQuantityIfPoLineIsPackageAndShouldDeleteHoldingAndItemAn .withPoLineEstimatedPrice(1d); Location loc = new Location().withHoldingId(holdingId).withQuantityElectronic(1).withQuantity(1); PoLine poLine = new PoLine().withIsPackage(true).withPurchaseOrderId(orderId).withId(lineId) - .withLocations(List.of(loc)).withCost(cost); + .withLocations(List.of(loc)).withCost(cost); PurchaseOrder purchaseOrder = new PurchaseOrder().withId(orderId).withWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN); Title title = new Title().withId(titleId); doReturn(succeededFuture(piece)).when(pieceStorageService).getPieceById(piece.getId(), requestContext); doReturn(succeededFuture(null)).when(protectionService).isOperationRestricted(any(), any(ProtectedOperationType.class), eq(requestContext)); - doReturn(succeededFuture(null)).when(pieceStorageService).deletePiece(piece.getId(), true,requestContext); + doReturn(succeededFuture(null)).when(pieceStorageService).deletePiece(piece.getId(), true, requestContext); doReturn(succeededFuture(null)).when(circulationRequestsRetriever).getNumberOfRequestsByItemId(piece.getItemId(), requestContext); doReturn(succeededFuture(item)).when(inventoryItemManager).getItemRecordById(itemId, true, requestContext); doReturn(succeededFuture(null)).when(inventoryItemManager).deleteItem(itemId, true, requestContext); @@ -171,7 +171,7 @@ void shouldNotUpdateLineQuantityIfPoLineIsPackageAndShouldDeleteHoldingAndItemAn doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, true, requestContext); doReturn(succeededFuture(null)).when(pieceUpdateInventoryService).deleteHoldingConnectedToPiece(piece, requestContext); - doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); + doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); final ArgumentCaptor pieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doReturn(succeededFuture(null)).when(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); @@ -192,7 +192,7 @@ void shouldNotUpdateLineQuantityIfPoLineIsPackageAndShouldDeleteHoldingAndItemAn } @Test - void shouldNotUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateTrueAndDeleteHoldingAndItemAndPiece() { + void shouldNotUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateTrueAndDeleteHoldingAndItemAndPiece() { String orderId = UUID.randomUUID().toString(); String holdingId = UUID.randomUUID().toString(); String lineId = UUID.randomUUID().toString(); @@ -222,7 +222,7 @@ void shouldNotUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateTrueAndD doReturn(succeededFuture(null)).when(inventoryItemManager).deleteItem(itemId, true, requestContext); doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, true, requestContext); doReturn(succeededFuture(null)).when(pieceUpdateInventoryService).deleteHoldingConnectedToPiece(piece, requestContext); - doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); + doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); final ArgumentCaptor PieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doAnswer((Answer>) invocation -> { PieceDeletionHolder answerHolder = invocation.getArgument(0); @@ -251,7 +251,7 @@ void shouldNotUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateTrueAndD } @Test - void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndDeleteOnlyPiece() { + void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndDeleteOnlyPiece() { String orderId = UUID.randomUUID().toString(); String lineId = UUID.randomUUID().toString(); String titleId = UUID.randomUUID().toString(); @@ -266,7 +266,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndDel .withPoLineEstimatedPrice(1d); PoLine poLine = new PoLine().withIsPackage(false).withCheckinItems(false).withOrderFormat(PoLine.OrderFormat.ELECTRONIC_RESOURCE) .withEresource(new Eresource().withCreateInventory(Eresource.CreateInventory.NONE)) - .withPurchaseOrderId(orderId).withId(lineId).withLocations(List.of(loc)).withCost(cost); + .withPurchaseOrderId(orderId).withId(lineId).withLocations(List.of(loc)).withCost(cost); PurchaseOrder purchaseOrder = new PurchaseOrder().withId(orderId).withWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN); Title title = new Title().withId(titleId); @@ -306,7 +306,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndDel } @Test - void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInventoryInstanceVsHoldingAndDeleteHoldingAndPiece() { + void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInventoryInstanceVsHoldingAndDeleteHoldingAndPiece() { String orderId = UUID.randomUUID().toString(); String holdingId = UUID.randomUUID().toString(); String lineId = UUID.randomUUID().toString(); @@ -319,7 +319,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv JsonObject item = new JsonObject().put(ID, itemId); item.put(ITEM_STATUS, new JsonObject().put(ITEM_STATUS_NAME, ItemStatus.ON_ORDER.value())); Piece piece = new Piece().withId(UUID.randomUUID().toString()).withPoLineId(lineId) - .withHoldingId(holdingId).withFormat(Piece.Format.ELECTRONIC); + .withHoldingId(holdingId).withFormat(Piece.Format.ELECTRONIC); Location loc = new Location().withHoldingId(holdingId).withQuantityElectronic(1).withQuantity(1); Cost cost = new Cost().withQuantityElectronic(1) .withListUnitPriceElectronic(1d).withExchangeRate(1d).withCurrency("USD") @@ -341,7 +341,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv doReturn(succeededFuture(null)).when(inventoryItemManager).deleteItem(itemId, true, requestContext); doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, true, requestContext); doReturn(succeededFuture(null)).when(pieceUpdateInventoryService).deleteHoldingConnectedToPiece(piece, requestContext); - doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); + doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); final ArgumentCaptor PieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doAnswer((Answer>) invocation -> { PieceDeletionHolder answerHolder = invocation.getArgument(0); @@ -369,7 +369,7 @@ void shouldUpdateLineQuantityIfPoLineIsNotPackageAndManualPieceCreateFalseAndInv } @Test - void shouldDeletePiecesInBatch() { + void shouldDeletePiecesInBatch() { String orderId = UUID.randomUUID().toString(); String holdingId = UUID.randomUUID().toString(); String lineId = UUID.randomUUID().toString(); @@ -407,7 +407,7 @@ void shouldDeletePiecesInBatch() { doReturn(succeededFuture(null)).when(inventoryItemManager).deleteItem(itemId, true, requestContext); doReturn(succeededFuture(holding)).when(inventoryHoldingManager).getHoldingById(holdingId, true, requestContext); doReturn(succeededFuture(null)).when(pieceUpdateInventoryService).deleteHoldingConnectedToPiece(piece, requestContext); - doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); + doReturn(succeededFuture(new ArrayList())).when(inventoryItemManager).getItemsByHoldingId(holdingId, requestContext); final ArgumentCaptor PieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doAnswer((Answer>) invocation -> { PieceDeletionHolder answerHolder = invocation.getArgument(0); @@ -423,34 +423,45 @@ void shouldDeletePiecesInBatch() { final ArgumentCaptor pieceDeletionHolderCapture = ArgumentCaptor.forClass(PieceDeletionHolder.class); doReturn(succeededFuture(null)).when(pieceDeleteFlowPoLineService).updatePoLine(pieceDeletionHolderCapture.capture(), eq(requestContext)); //When - pieceDeleteFlowManager.batchDeletePiece(pieceCollection, requestContext).result(); + pieceDeleteFlowManager.batchDeletePiece(pieceCollection, requestContext).result(); verify(pieceStorageService).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); verify(inventoryItemManager, times(0)).deleteItem(itemId, true, requestContext); verify(pieceStorageService, times(1)).deletePiece(eq(piece.getId()), eq(true), eq(requestContext)); } private static class ContextConfiguration { - @Bean PieceStorageService pieceStorageService() { + @Bean + PieceStorageService pieceStorageService() { return mock(PieceStorageService.class); } - @Bean ProtectionService protectionService() { + + @Bean + ProtectionService protectionService() { return mock(ProtectionService.class); } - @Bean PieceDeleteFlowPoLineService pieceDeleteFlowPoLineService() { + @Bean + PieceDeleteFlowPoLineService pieceDeleteFlowPoLineService() { return mock(PieceDeleteFlowPoLineService.class); } - @Bean InventoryItemManager inventoryItemManager() { + + @Bean + InventoryItemManager inventoryItemManager() { return mock(InventoryItemManager.class); } - @Bean InventoryHoldingManager inventoryHoldingManager() { + + @Bean + InventoryHoldingManager inventoryHoldingManager() { return mock(InventoryHoldingManager.class); } - @Bean PieceUpdateInventoryService pieceUpdateInventoryService() { + + @Bean + PieceUpdateInventoryService pieceUpdateInventoryService() { return mock(PieceUpdateInventoryService.class); } - @Bean BasePieceFlowHolderBuilder basePieceFlowHolderBuilder() { + @Bean + BasePieceFlowHolderBuilder basePieceFlowHolderBuilder() { return mock(BasePieceFlowHolderBuilder.class); } @@ -459,15 +470,15 @@ public CirculationRequestsRetriever circulationRequestsRetriever() { return mock(CirculationRequestsRetriever.class); } - @Bean PieceDeleteFlowManager pieceDeleteFlowManager(PieceStorageService pieceStorageService, - ProtectionService protectionService, - InventoryItemManager inventoryItemManager, - PieceUpdateInventoryService pieceUpdateInventoryService, - PieceDeleteFlowPoLineService pieceDeleteFlowPoLineService, - BasePieceFlowHolderBuilder basePieceFlowHolderBuilder, - CirculationRequestsRetriever circulationRequestsRetriever) { - return new PieceDeleteFlowManager(pieceStorageService, protectionService, inventoryItemManager, - pieceUpdateInventoryService, pieceDeleteFlowPoLineService, basePieceFlowHolderBuilder, circulationRequestsRetriever); + @Bean + PieceDeleteFlowManager pieceDeleteFlowManager(PieceDeleteFlowInventoryManager pieceDeleteFlowInventoryManager, + PieceStorageService pieceStorageService, + ProtectionService protectionService, + PieceDeleteFlowPoLineService pieceDeleteFlowPoLineService, + BasePieceFlowHolderBuilder basePieceFlowHolderBuilder, + CirculationRequestsRetriever circulationRequestsRetriever) { + return new PieceDeleteFlowManager(pieceDeleteFlowInventoryManager, pieceStorageService, protectionService, + pieceDeleteFlowPoLineService, basePieceFlowHolderBuilder, circulationRequestsRetriever); } } }