Skip to content

Commit

Permalink
MODORDERS-1149. 500 response when changing the instance connection wi…
Browse files Browse the repository at this point in the history
…th "Create new" option (#995)

* MODORDERS-1149. 500 response when changing the instance connection with "Create new" option
  • Loading branch information
SerhiiNosko authored Aug 19, 2024
1 parent fd15c05 commit 2fe3c48
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.folio.rest.jaxrs.model.Location;
import org.folio.rest.jaxrs.model.ProductId;
import org.folio.rest.jaxrs.model.Title;
import org.folio.rest.tools.utils.TenantTool;
import org.folio.service.caches.ConfigurationEntriesCache;
import org.folio.service.caches.InventoryCache;
import org.folio.service.consortium.ConsortiumConfigurationService;
Expand Down Expand Up @@ -401,13 +402,15 @@ private Future<SharingInstance> createShadowInstanceIfNeeded(String instanceId,
logger.info("createShadowInstanceIfNeeded:: Provided instanceId is blank, skip creating of shadow instance.");
return Future.succeededFuture();
}
var targetTenant = TenantTool.tenantId(requestContext.getHeaders());
logger.info("createShadowInstanceIfNeeded:: Getting instance: {} from tenant: {}", instanceId, targetTenant);
return getInstanceById(instanceId, true, requestContext)
.compose(instance -> {
if (Objects.nonNull(instance) && !instance.isEmpty()) {
logger.info("createShadowInstanceIfNeeded:: Shadow instance already exists, skipping...");
logger.info("createShadowInstanceIfNeeded:: Shadow instance {} already exists in tenant: {}, skipping...", instanceId, targetTenant);
return Future.succeededFuture();
}
logger.info("createShadowInstanceIfNeeded:: Creating shadow instance with instanceId: {}", instanceId);
logger.info("createShadowInstanceIfNeeded:: Creating shadow instance with instanceId: {} in tenant: {}", instanceId, targetTenant);
return sharingInstanceService.createShadowInstance(instanceId, consortiumConfiguration, requestContext);
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package org.folio.service.orders.lines.update.instance;

import io.vertx.core.Future;
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonObject;
import one.util.streamex.StreamEx;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.folio.models.orders.lines.update.OrderLineUpdateInstanceHolder;
import org.folio.okapi.common.GenericCompositeFuture;
import org.folio.orders.utils.PoLineCommonUtil;
Expand All @@ -31,6 +34,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;
Expand All @@ -40,6 +44,8 @@

public class WithHoldingOrderLineUpdateInstanceStrategy extends BaseOrderLineUpdateInstanceStrategy {

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

private static final String HOLDINGS_ITEMS = "holdingsItems";
private static final String BARE_HOLDINGS_ITEMS = "bareHoldingsItems";
private final PieceStorageService pieceStorageService;
Expand Down Expand Up @@ -136,14 +142,8 @@ private void removeHoldingUnrecognizedFields(List<JsonObject> holdings) {

private Future<Void> findOrCreateHoldingsAndUpdateItems(OrderLineUpdateInstanceHolder holder,
String newInstanceId, RequestContext requestContext) {
return retrieveUniqueLocations(holder.getStoragePoLine(), requestContext)
.compose(locations -> GenericCompositeFuture.join(
locations.stream()
.map(location -> findOrCreateHoldingsAndUpdateItems(holder, newInstanceId, location, requestContext))
.toList()
)
)
.mapEmpty();
return processLocations(holder, requestContext,
location -> findOrCreateHoldingsAndUpdateItems(holder, newInstanceId, location, requestContext));
}

private Future<Void> findOrCreateHoldingsAndUpdateItems(OrderLineUpdateInstanceHolder holder,
Expand All @@ -153,7 +153,10 @@ private Future<Void> findOrCreateHoldingsAndUpdateItems(OrderLineUpdateInstanceH
PoLine poLine = holder.getStoragePoLine();
String holdingId = location.getHoldingId();
var locationContext = RequestContextUtil.createContextWithNewTenantId(requestContext, location.getTenantId());
return inventoryHoldingManager.getOrCreateHoldingRecordByInstanceAndLocation(newInstanceId, location, locationContext)
logger.info("findOrCreateHoldingsAndUpdateItems:: start processing for new instanceId: {}, holdingId: {}, tenantId(for ECS): {}",
newInstanceId, holdingId, location.getTenantId());
return inventoryInstanceManager.createShadowInstanceIfNeeded(newInstanceId, locationContext)
.compose(instance -> inventoryHoldingManager.getOrCreateHoldingRecordByInstanceAndLocation(newInstanceId, location, locationContext))
.compose(newHoldingId -> {
holder.addHoldingRefsToStoragePatchOrderLineRequest(holdingId, newHoldingId);
if (Objects.equals(holdingId, newHoldingId)) {
Expand All @@ -165,14 +168,8 @@ private Future<Void> findOrCreateHoldingsAndUpdateItems(OrderLineUpdateInstanceH

private Future<Void> createHoldingsAndUpdateItems(OrderLineUpdateInstanceHolder holder,
String newInstanceId, RequestContext requestContext) {
return retrieveUniqueLocations(holder.getStoragePoLine(), requestContext)
.compose(locations -> GenericCompositeFuture.join(
locations.stream()
.map(location -> createHoldingsAndUpdateItems(holder, newInstanceId, location, requestContext))
.toList()
)
)
.mapEmpty();
return processLocations(holder, requestContext,
location -> createHoldingsAndUpdateItems(holder, newInstanceId, location, requestContext));
}

private Future<Void> createHoldingsAndUpdateItems(OrderLineUpdateInstanceHolder holder,
Expand All @@ -182,26 +179,51 @@ private Future<Void> createHoldingsAndUpdateItems(OrderLineUpdateInstanceHolder
PoLine poLine = holder.getStoragePoLine();
String holdingId = location.getHoldingId();
var locationContext = RequestContextUtil.createContextWithNewTenantId(requestContext, location.getTenantId());
return inventoryHoldingManager.createHolding(newInstanceId, location, locationContext)
logger.info("createHoldingsAndUpdateItems:: start processing for new instanceId: {}, holdingId: {}, tenantId(for ECS): {}",
newInstanceId, holdingId, location.getTenantId());
return inventoryInstanceManager.createShadowInstanceIfNeeded(newInstanceId, locationContext)
.compose(instance -> inventoryHoldingManager.createHolding(newInstanceId, location, locationContext))
.compose(newHoldingId -> {
holder.addHoldingRefsToStoragePatchOrderLineRequest(holdingId, newHoldingId);
return updateItemsHolding(holdingId, newHoldingId, poLine.getId(), locationContext);
});
}

private Future<List<Location>> retrieveUniqueLocations(PoLine poLine, RequestContext requestContext) {
private Future<Void> processLocations(OrderLineUpdateInstanceHolder holder,
RequestContext requestContext,
Function<Location, Future<Void>> processFunction) {
return retrieveUniqueLocations(holder.getStoragePoLine(), requestContext)
.compose(tenantIdToLocationsMap ->
GenericCompositeFuture.all(tenantIdToLocationsMap.values().stream()
.map(locations ->
GenericCompositeFuture.join(locations.stream()
.map(processFunction)
.toList())
)
.collect(toList()))
)
.mapEmpty();
}

private Future<Map<String, List<Location>>> retrieveUniqueLocations(PoLine poLine, RequestContext requestContext) {
return pieceStorageService.getPiecesByPoLineId(PoLineCommonUtil.convertToCompositePoLine(poLine), requestContext)
.map(pieces -> {
List<Location> pieceHoldingIds = pieces
.stream()
.map(piece -> new Location().withHoldingId(piece.getHoldingId()).withLocationId(piece.getLocationId()))
.map(piece -> new Location()
.withHoldingId(piece.getHoldingId())
.withLocationId(piece.getLocationId())
.withTenantId(piece.getReceivingTenantId()))
.collect(toList());
List<Location> storageHoldingIds = poLine.getLocations();

return StreamEx.of(ListUtils.union(pieceHoldingIds, storageHoldingIds))
List<Location> uniqueLocations = StreamEx.of(ListUtils.union(pieceHoldingIds, storageHoldingIds))
.distinct(location -> String.format("%s %s", location.getLocationId(), location.getHoldingId()))
.filter(location -> Objects.nonNull(location.getHoldingId()))
.toList();
logger.info("retrieveUniqueLocations:: list of result locations: {}", Json.encodePrettily(uniqueLocations));
return uniqueLocations.stream()
.collect(Collectors.groupingBy(location -> Objects.requireNonNullElse(location.getTenantId(), TenantTool.tenantId(requestContext.getHeaders()))));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ public void updateInstanceForFindOrCreateHoldingOperation() throws IOException {
return item;
}).collect(toList());

doReturn(succeededFuture()).when(inventoryInstanceManager).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
.getOrCreateHoldingRecordByInstanceAndLocation(eq(instanceId), eq(locations.get(0)), eq(requestContext));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
Expand All @@ -236,6 +237,7 @@ public void updateInstanceForFindOrCreateHoldingOperation() throws IOException {

withHoldingOrderLineUpdateInstanceStrategy.updateInstance(orderLineUpdateInstanceHolder, requestContext).result();

verify(inventoryInstanceManager, times(2)).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
verify(inventoryHoldingManager, times(1)).getOrCreateHoldingRecordByInstanceAndLocation(instanceId, locations.get(0), requestContext);
verify(inventoryHoldingManager, times(1)).getOrCreateHoldingRecordByInstanceAndLocation(instanceId, locations.get(1), requestContext);
verify(inventoryItemManager, times(2)).getItemsByHoldingIdAndOrderLineId(anyString(), anyString(), any(RequestContext.class));
Expand Down Expand Up @@ -281,13 +283,15 @@ public void updateInstanceAndItemsForFindOrCreateHoldingOperation() throws IOExc
item.put(ITEM_STATUS, new JsonObject().put(ITEM_STATUS_NAME, ItemStatus.ON_ORDER.value()));
item.put(ITEM_HOLDINGS_RECORD_ID, holdingId);

doReturn(succeededFuture()).when(inventoryInstanceManager).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
.getOrCreateHoldingRecordByInstanceAndLocation(eq(instanceId), eq(locations.get(0)), eq(requestContext));
doReturn(succeededFuture(List.of(item))).when(inventoryItemManager).getItemsByHoldingIdAndOrderLineId(eq(holdingId), eq(orderLineId), eq(requestContext));
doReturn(succeededFuture(null)).when(inventoryItemManager).updateItem(eq(item), eq(requestContext));

withHoldingOrderLineUpdateInstanceStrategy.updateInstance(orderLineUpdateInstanceHolder, requestContext).result();

verify(inventoryInstanceManager, times(1)).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
verify(inventoryHoldingManager, times(1)).getOrCreateHoldingRecordByInstanceAndLocation(instanceId, locations.get(0), requestContext);
verify(inventoryItemManager, times(1)).getItemsByHoldingIdAndOrderLineId(holdingId, orderLineId, requestContext);
verify(inventoryItemManager, times(1)).updateItem(item, requestContext);
Expand Down Expand Up @@ -327,11 +331,13 @@ public void updateInstanceAndNotUpdateItemsForFindOrCreateHoldingOperationWhenHo
.withStoragePoLine(poLine)
.withPathOrderLineRequest(patchOrderLineRequest);

doReturn(succeededFuture()).when(inventoryInstanceManager).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
doReturn(succeededFuture(holdingId)).when(inventoryHoldingManager)
.getOrCreateHoldingRecordByInstanceAndLocation(eq(instanceId), eq(locations.get(0)), eq(requestContext));

withHoldingOrderLineUpdateInstanceStrategy.updateInstance(orderLineUpdateInstanceHolder, requestContext).result();

verify(inventoryInstanceManager, times(1)).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
verify(inventoryHoldingManager, times(1)).getOrCreateHoldingRecordByInstanceAndLocation(instanceId, locations.get(0), requestContext);
verify(inventoryItemManager, never()).getItemsByHoldingIdAndOrderLineId(anyString(), anyString(), any(RequestContext.class));
verify(inventoryItemManager, never()).updateItem(any(JsonObject.class), any(RequestContext.class));
Expand Down Expand Up @@ -385,7 +391,7 @@ public void updateInstanceForFindOrCreateHoldingOperationAndDeleteAbandonedHoldi
return item;
}).collect(toList());


doReturn(succeededFuture()).when(inventoryInstanceManager).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
.getOrCreateHoldingRecordByInstanceAndLocation(eq(instanceId), eq(locations.get(0)), eq(requestContext));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
Expand All @@ -401,6 +407,7 @@ public void updateInstanceForFindOrCreateHoldingOperationAndDeleteAbandonedHoldi
var future = withHoldingOrderLineUpdateInstanceStrategy.updateInstance(orderLineUpdateInstanceHolder, requestContext);

vertxTestContext.assertComplete(future).onComplete(res-> {
verify(inventoryInstanceManager, times(2)).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
verify(inventoryHoldingManager, times(1)).getOrCreateHoldingRecordByInstanceAndLocation(instanceId, locations.get(0), requestContext);
verify(inventoryHoldingManager, times(1)).getOrCreateHoldingRecordByInstanceAndLocation(instanceId, locations.get(1), requestContext);
verify(inventoryHoldingManager, times(1)).deleteHoldingById(eq(holdingIds.get(0)), eq(true), any(RequestContext.class));
Expand Down Expand Up @@ -459,6 +466,7 @@ public void updateInstanceForCreateHoldingOperation() throws IOException {
OrderLineUpdateInstanceHolder orderLineUpdateInstanceHolder = new OrderLineUpdateInstanceHolder()
.withStoragePoLine(poLine).withPathOrderLineRequest(patchOrderLineRequest);

doReturn(succeededFuture()).when(inventoryInstanceManager).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
.createHolding(eq(instanceId), eq(locations.get(0)), eq(requestContext));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
Expand All @@ -469,6 +477,7 @@ public void updateInstanceForCreateHoldingOperation() throws IOException {

withHoldingOrderLineUpdateInstanceStrategy.updateInstance(orderLineUpdateInstanceHolder, requestContext).result();

verify(inventoryInstanceManager, times(2)).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
verify(inventoryHoldingManager, times(1)).createHolding(instanceId, locations.get(0), requestContext);
verify(inventoryHoldingManager, times(1)).createHolding(instanceId, locations.get(1), requestContext);
verify(inventoryItemManager, times(2)).getItemsByHoldingIdAndOrderLineId(anyString(), anyString(), any(RequestContext.class));
Expand Down Expand Up @@ -514,13 +523,15 @@ public void updateInstanceAndItemsForCreateHoldingOperation() throws IOException
OrderLineUpdateInstanceHolder orderLineUpdateInstanceHolder = new OrderLineUpdateInstanceHolder()
.withStoragePoLine(poLine).withPathOrderLineRequest(patchOrderLineRequest);

doReturn(succeededFuture()).when(inventoryInstanceManager).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
.createHolding(eq(instanceId), eq(locations.get(0)), eq(requestContext));
doReturn(succeededFuture(List.of(item))).when(inventoryItemManager).getItemsByHoldingIdAndOrderLineId(eq(holdingId), eq(orderLineId), eq(requestContext));
doReturn(succeededFuture(null)).when(inventoryItemManager).updateItem(eq(item), eq(requestContext));

withHoldingOrderLineUpdateInstanceStrategy.updateInstance(orderLineUpdateInstanceHolder, requestContext).result();

verify(inventoryInstanceManager, times(1)).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
verify(inventoryHoldingManager, times(1)).createHolding(instanceId, locations.get(0), requestContext);
verify(inventoryItemManager, times(1)).getItemsByHoldingIdAndOrderLineId(holdingId, orderLineId, requestContext);
verify(inventoryItemManager, times(1)).updateItem(item, requestContext);
Expand Down Expand Up @@ -565,6 +576,7 @@ public void updateInstanceAndItemsWithItemsNotUpdatesCorrect(VertxTestContext ve
OrderLineUpdateInstanceHolder orderLineUpdateInstanceHolder = new OrderLineUpdateInstanceHolder()
.withStoragePoLine(poLine).withPathOrderLineRequest(patchOrderLineRequest);

doReturn(succeededFuture()).when(inventoryInstanceManager).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
doReturn(succeededFuture(UUID.randomUUID().toString())).when(inventoryHoldingManager)
.createHolding(eq(instanceId), eq(locations.get(0)), eq(requestContext));
doReturn(succeededFuture(List.of(item))).when(inventoryItemManager).getItemsByHoldingIdAndOrderLineId(eq(holdingId), eq(orderLineId), eq(requestContext));
Expand All @@ -582,6 +594,7 @@ public void updateInstanceAndItemsWithItemsNotUpdatesCorrect(VertxTestContext ve
Assertions.assertEquals("itemId", actParameter.getKey());
Assertions.assertEquals(itemId, actParameter.getValue());

verify(inventoryInstanceManager, times(1)).createShadowInstanceIfNeeded(eq(instanceId), any(RequestContext.class));
verify(inventoryHoldingManager, times(1)).createHolding(instanceId, locations.get(0), requestContext);
verify(inventoryItemManager, times(1)).getItemsByHoldingIdAndOrderLineId(holdingId, orderLineId, requestContext);
verify(inventoryItemManager, times(1)).updateItem(item, requestContext);
Expand Down

0 comments on commit 2fe3c48

Please sign in to comment.