Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/MODORDERS-989' into MODORDERS-989
Browse files Browse the repository at this point in the history
  • Loading branch information
Khamidulla Abdulkhakimov authored and Khamidulla Abdulkhakimov committed Jan 17, 2024
2 parents e87c1dd + 62f984c commit acdc689
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 2 deletions.
34 changes: 34 additions & 0 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,34 @@
"orders-storage.reporting-codes.item.get"
]
},
{
"methods": [
"POST"
],
"pathPattern": "/orders/restore",
"permissionsRequired": [
"orders.restore.collection.post"
],
"modulePermissions": [
"orders-storage.pieces.collection.get",
"orders-storage.pieces.item.put",
"orders-storage.po-lines.collection.get",
"orders-storage.po-lines.item.put",
"orders-storage.purchase-orders.item.get",
"orders-storage.purchase-orders.item.put",
"orders-storage.titles.collection.get",
"inventory.items.collection.get",
"inventory.items.item.put",
"inventory-storage.holdings.collection.get",
"inventory-storage.holdings.item.post",
"acquisitions-units-storage.units.collection.get",
"acquisitions-units-storage.memberships.collection.get",
"orders-storage.purchase-orders.collection.get",
"finance.encumbrances.item.put",
"finance.order-transaction-summaries.item.put",
"finance.transactions.collection.get"
]
},
{
"methods": [
"GET"
Expand Down Expand Up @@ -1277,6 +1305,11 @@
"displayName": "Orders - Check-in items",
"description": "Check-in items spanning one or more po-lines in this order"
},
{
"permissionName": "orders.restore.collection.post",
"displayName": "Orders - Restore items",
"description": "Restore items spanning one or more po-lines in this order"
},
{
"permissionName": "orders.receiving-history.collection.get",
"displayName": "Orders - Receiving history",
Expand Down Expand Up @@ -1697,6 +1730,7 @@
"orders.po-number.item.post",
"orders.receiving.collection.post",
"orders.check-in.collection.post",
"orders.restore.collection.post",
"orders.receiving-history.collection.get",
"orders.pieces.all",
"orders.acquisitions-units-assignments.all",
Expand Down
38 changes: 38 additions & 0 deletions ramls/restoration.raml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#%RAML 1.0
title: Restoration
baseUri: https://github.com/folio-org/mod-orders
version: v1
protocols: [ HTTP, HTTPS ]

documentation:
- title: Orders Business Logic API
content: <b>API for transition pieces status from unreceivable to expected</b>

types:
receiving-collection: !include acq-models/mod-orders/schemas/receivingCollection.json
receiving-results: !include acq-models/mod-orders/schemas/receivingResults.json
errors: !include raml-util/schemas/errors.schema
UUID:
type: string
pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$

traits:
validate: !include raml-util/traits/validation.raml

resourceTypes:
post-with-200: !include rtypes/post-json-200.raml

/orders/restore:
displayName: Restore items
description: |
Restore items spanning one or more PO lines. The endpoint is used to:
- move a received piece back to "Expected" in case "receivedItems" element's "itemStatus" is "On order"
type:
post-with-200:
requestSchema: receiving-collection
responseSchema: receiving-results
requestExample: !include acq-models/mod-orders/examples/receivingCollection.sample
responseExample: !include acq-models/mod-orders/examples/receivingResults.sample
is: [validate]
post:
description: Restore items spanning one or more PO lines
2 changes: 1 addition & 1 deletion src/main/java/org/folio/helper/ReceivingHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ protected Map<String, List<Piece>> updatePieceRecordsWithoutItems(Map<String, Li
* @param piece
* piece record to be updated with receiving info
*/
private void updatePieceWithReceivingInfo(Piece piece) {
protected void updatePieceWithReceivingInfo(Piece piece) {
// Get ReceivedItem corresponding to piece record
ReceivedItem receivedItem = piecesByLineId.get(piece.getPoLineId())
.get(piece.getId());
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/org/folio/helper/RestoreHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.folio.helper;

import io.vertx.core.Context;
import io.vertx.core.Future;
import org.folio.rest.core.models.RequestContext;
import org.folio.rest.jaxrs.model.Piece;
import org.folio.rest.jaxrs.model.ReceivingCollection;
import org.folio.rest.jaxrs.model.ReceivingResults;

import java.util.Map;

public class RestoreHelper extends ReceivingHelper {

public RestoreHelper(ReceivingCollection receivingCollection, Map<String, String> okapiHeaders, Context ctx) {
super(receivingCollection, okapiHeaders, ctx);
}

public Future<ReceivingResults> restorePiece(ReceivingCollection restorationCollection, RequestContext requestContext) {
return receiveItems(restorationCollection, requestContext);
}

@Override
protected boolean isRevertToOnOrder(Piece piece) {
return piece.getReceivingStatus() == Piece.ReceivingStatus.UNRECEIVABLE
&& inventoryManager
.isOnOrderItemStatus(piecesByLineId.get(piece.getPoLineId()).get(piece.getId()));
}

@Override
protected void updatePieceWithReceivingInfo(Piece piece) {
super.updatePieceWithReceivingInfo(piece);

piece.setReceivedDate(null);
piece.setReceivingStatus(Piece.ReceivingStatus.EXPECTED);
}
}
13 changes: 12 additions & 1 deletion src/main/java/org/folio/rest/impl/ReceivingAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@
import org.apache.logging.log4j.Logger;
import org.folio.helper.CheckinHelper;
import org.folio.helper.ReceivingHelper;
import org.folio.helper.RestoreHelper;
import org.folio.rest.annotations.Validate;
import org.folio.rest.core.models.RequestContext;
import org.folio.rest.jaxrs.model.CheckinCollection;
import org.folio.rest.jaxrs.model.ReceivingCollection;
import org.folio.rest.jaxrs.resource.OrdersCheckIn;
import org.folio.rest.jaxrs.resource.OrdersReceive;
import org.folio.rest.jaxrs.resource.OrdersRestore;
import org.folio.rest.jaxrs.resource.OrdersReceivingHistory;

import io.vertx.core.AsyncResult;
import io.vertx.core.Context;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;

public class ReceivingAPI implements OrdersReceive, OrdersCheckIn, OrdersReceivingHistory {
public class ReceivingAPI implements OrdersReceive, OrdersCheckIn, OrdersReceivingHistory, OrdersRestore {

private static final Logger logger = LogManager.getLogger();

Expand Down Expand Up @@ -66,4 +68,13 @@ public void getOrdersReceivingHistory(String totalRecords, int offset, int limit
})
.onFailure(t -> handleErrorResponse(asyncResultHandler, helper, t));
}

@Override
public void postOrdersRestore(ReceivingCollection entity, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
logger.info("Restoring {} items", entity.getTotalRecords());
RestoreHelper helper = new RestoreHelper(entity, okapiHeaders, vertxContext);
helper.restorePiece(entity, new RequestContext(vertxContext, okapiHeaders))
.onSuccess(result -> asyncResultHandler.handle(succeededFuture(helper.buildOkResponse(result))))
.onFailure(t -> handleErrorResponse(asyncResultHandler, helper, t));
}
}
1 change: 1 addition & 0 deletions src/test/java/org/folio/TestConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ private TestConstants() {}

public static final String ORDERS_RECEIVING_ENDPOINT = "/orders/receive";
public static final String ORDERS_CHECKIN_ENDPOINT = "/orders/check-in";
public static final String ORDERS_RESTORE_ENDPOINT = "/orders/restore";

public static final String PO_LINE_NUMBER_VALUE = "1";

Expand Down
46 changes: 46 additions & 0 deletions src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10;
import static org.folio.TestConstants.ORDERS_CHECKIN_ENDPOINT;
import static org.folio.TestConstants.ORDERS_RECEIVING_ENDPOINT;
import static org.folio.TestConstants.ORDERS_RESTORE_ENDPOINT;
import static org.folio.TestUtils.getInstanceId;
import static org.folio.TestUtils.getMinimalContentCompositePoLine;
import static org.folio.TestUtils.getMinimalContentCompositePurchaseOrder;
Expand Down Expand Up @@ -111,6 +112,7 @@ public class CheckinReceivingApiTest {

private static final String RECEIVING_RQ_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "receiving/";
private static final String CHECKIN_RQ_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "checkIn/";
private static final String RESTORE_RQ_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "restore/";
private static final String ITEM_BARCODE = "barcode";
private static final String ITEM_LEVEL_CALL_NUMBER = "itemLevelCallNumber";
private static final String HOLDING_PERMANENT_LOCATION_ID = "permanentLocationId";
Expand Down Expand Up @@ -1025,6 +1027,50 @@ void testPostReceivingRevertElectronicResource() {
verifyOrderStatusUpdateEvent(1);
}

@Test
void testRestoreUnreceivablePiece() {
logger.info("=== Test POST Restore");

CompositePoLine poLines = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(9).mapTo(CompositePoLine.class);
MockServer.addMockTitles(Collections.singletonList(poLines));

ReceivingCollection receivingRq = getMockAsJson(RESTORE_RQ_MOCK_DATA_PATH + "receive-physical-ongoing.json").mapTo(ReceivingCollection.class);
receivingRq.getToBeReceived().get(0).setPoLineId(COMPOSITE_POLINE_ONGOING_ID);

ReceivingResults results = verifyPostResponse(ORDERS_RESTORE_ENDPOINT, JsonObject.mapFrom(receivingRq).encode(),
prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10), APPLICATION_JSON, 200).as(ReceivingResults.class);

assertThat(results.getTotalRecords(), equalTo(receivingRq.getTotalRecords()));

Map<String, Set<String>> pieceIdsByPol = verifyReceivingSuccessRs(results);

List<JsonObject> pieceSearches = getPieceSearches();
List<JsonObject> pieceUpdates = getPieceUpdates();
List<JsonObject> polSearches = getPoLineSearches();
List<JsonObject> polUpdates = getPoLineUpdates();

assertThat(pieceSearches, not(nullValue()));
assertThat(pieceUpdates, not(nullValue()));

assertThat(polSearches, not(nullValue()));

int expectedSearchRqQty = Math.floorDiv(receivingRq.getTotalRecords(), MAX_IDS_FOR_GET_RQ_15) + 1;

// The piece searches should be made 1 time: 1st time to get all required piece records
assertThat(pieceSearches, hasSize(expectedSearchRqQty));
assertThat(pieceUpdates, hasSize(receivingRq.getTotalRecords()));
assertThat(pieceUpdates, hasSize(1));

pieceUpdates.forEach(pieceUpdated -> {
Piece pieceMapped = pieceUpdated.mapTo(Piece.class);
assertThat(pieceMapped.getReceivedDate(), nullValue());
assertThat(pieceMapped.getReceivingStatus(), is(Piece.ReceivingStatus.EXPECTED));
});

// Verify no status updated for ongoing order
verifyOrderStatusUpdateEvent(0);
}

private void checkResultWithErrors(CheckinCollection request, int expectedNumOfErrors) {

ReceivingResult response = verifyPostResponse(ORDERS_CHECKIN_ENDPOINT, JsonObject.mapFrom(request).encode(),
Expand Down
20 changes: 20 additions & 0 deletions src/test/resources/mockdata/restore/receive-physical-ongoing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"toBeReceived": [
{
"poLineId": "0dd8f1d2-ac2e-4155-a407-72071f6d5f4a",
"received": 1,
"receivedItems": [
{
"barcode": 21111111122,
"callNumber": "PR 8923 W6 L36 1990 c.3",
"comment": "Very important note",
"caption": "Vol. 1",
"itemStatus": "On order",
"locationId": "fcd64ce1-6995-48f0-840e-89ffa2288371",
"pieceId": "05a95f03-eb00-4248-9f2e-2bd05957ff04"
}
]
}
],
"totalRecords": 1
}

0 comments on commit acdc689

Please sign in to comment.