Search in sources :

Example 6 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class HoldingsUpdateDelegate method updateHoldingsRecord.

private Future<HoldingsRecord> updateHoldingsRecord(HoldingsRecord holdingsRecord, HoldingsRecordCollection holdingsRecordCollection) {
    Promise<HoldingsRecord> promise = Promise.promise();
    holdingsRecordCollection.update(holdingsRecord, success -> promise.complete(holdingsRecord), failure -> {
        if (failure.getStatusCode() == HttpStatus.SC_CONFLICT) {
            promise.fail(new OptimisticLockingException(failure.getReason()));
        } else {
            LOGGER.error(format("Error updating Holdings - %s, status code %s", failure.getReason(), failure.getStatusCode()));
            promise.fail(failure.getReason());
        }
    });
    return promise.future();
}
Also used : HoldingsRecord(org.folio.HoldingsRecord) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException)

Example 7 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class UpdateHoldingEventHandler method handle.

@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
    CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
    try {
        dataImportEventPayload.setEventType(DI_INVENTORY_HOLDING_UPDATED.value());
        if (dataImportEventPayload.getContext() == null || isEmpty(dataImportEventPayload.getContext().get(HOLDINGS.value())) || isEmpty(dataImportEventPayload.getContext().get(MARC_BIBLIOGRAPHIC.value()))) {
            throw new EventProcessingException(CONTEXT_EMPTY_ERROR_MESSAGE);
        }
        if (dataImportEventPayload.getCurrentNode().getChildSnapshotWrappers().isEmpty()) {
            LOGGER.error(ACTION_HAS_NO_MAPPING_MSG);
            return CompletableFuture.failedFuture(new EventProcessingException(ACTION_HAS_NO_MAPPING_MSG));
        }
        LOGGER.info("Processing UpdateHoldingEventHandler starting with jobExecutionId: {}.", dataImportEventPayload.getJobExecutionId());
        HoldingsRecord tmpHoldingsRecord = retrieveHolding(dataImportEventPayload.getContext());
        String holdingId = tmpHoldingsRecord.getId();
        String hrid = tmpHoldingsRecord.getHrid();
        String instanceId = tmpHoldingsRecord.getInstanceId();
        String permanentLocationId = tmpHoldingsRecord.getPermanentLocationId();
        if (StringUtils.isAnyBlank(hrid, instanceId, permanentLocationId, holdingId)) {
            throw new EventProcessingException(EMPTY_REQUIRED_FIELDS_ERROR_MESSAGE);
        }
        Context context = constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
        String jobExecutionId = dataImportEventPayload.getJobExecutionId();
        String recordId = dataImportEventPayload.getContext().get(RECORD_ID_HEADER);
        String chunkId = dataImportEventPayload.getContext().get(CHUNK_ID_HEADER);
        mappingMetadataCache.get(jobExecutionId, context).map(parametersOptional -> parametersOptional.orElseThrow(() -> new EventProcessingException(format(MAPPING_METADATA_NOT_FOUND_MESSAGE, jobExecutionId, recordId, chunkId)))).onSuccess(mappingMetadataDto -> {
            prepareEvent(dataImportEventPayload);
            MappingParameters mappingParameters = Json.decodeValue(mappingMetadataDto.getMappingParams(), MappingParameters.class);
            MappingManager.map(dataImportEventPayload, new MappingContext().withMappingParameters(mappingParameters));
            HoldingsRecordCollection holdingsRecords = storage.getHoldingsRecordCollection(context);
            HoldingsRecord holding = retrieveHolding(dataImportEventPayload.getContext());
            holdingsRecords.update(holding, holdingSuccess -> constructDataImportEventPayload(future, dataImportEventPayload, holding), failure -> {
                if (failure.getStatusCode() == HttpStatus.SC_CONFLICT) {
                    processOLError(dataImportEventPayload, future, holdingsRecords, holding, failure);
                } else {
                    dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
                    LOGGER.error(format(CANNOT_UPDATE_HOLDING_ERROR_MESSAGE, holding.getId(), jobExecutionId, recordId, chunkId, failure.getReason(), failure.getStatusCode()));
                    future.completeExceptionally(new EventProcessingException(format(UPDATE_HOLDING_ERROR_MESSAGE, jobExecutionId, recordId, chunkId)));
                }
            });
        }).onFailure(e -> {
            LOGGER.error("Error updating inventory Holdings by jobExecutionId: '{}'", jobExecutionId, e);
            future.completeExceptionally(e);
        });
    } catch (Exception e) {
        LOGGER.error("Failed to update Holdings", e);
        future.completeExceptionally(e);
    }
    return future;
}
Also used : Context(org.folio.inventory.common.Context) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) MappingContext(org.folio.processing.mapping.mapper.MappingContext) Json(io.vertx.core.json.Json) Context(org.folio.inventory.common.Context) EventHandler(org.folio.processing.events.services.handler.EventHandler) MappingManager(org.folio.processing.mapping.MappingManager) HttpStatus(org.apache.http.HttpStatus) Failure(org.folio.inventory.common.domain.Failure) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ACTION_PROFILE(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.ACTION_PROFILE) StringUtils(org.apache.commons.lang3.StringUtils) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) HOLDINGS(org.folio.ActionProfile.FolioRecord.HOLDINGS) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) ProfileSnapshotWrapper(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper) ObjectMapperTool(org.folio.dbschema.ObjectMapperTool) JsonObject(io.vertx.core.json.JsonObject) Objects.isNull(java.util.Objects.isNull) ActionProfile(org.folio.ActionProfile) StringUtils.isEmpty(org.apache.commons.lang3.StringUtils.isEmpty) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) MARC_BIBLIOGRAPHIC(org.folio.ActionProfile.FolioRecord.MARC_BIBLIOGRAPHIC) MappingContext(org.folio.processing.mapping.mapper.MappingContext) DataImportEventPayload(org.folio.DataImportEventPayload) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) HoldingsRecord(org.folio.HoldingsRecord) String.format(java.lang.String.format) DI_INVENTORY_HOLDING_UPDATED(org.folio.DataImportEventTypes.DI_INVENTORY_HOLDING_UPDATED) Storage(org.folio.inventory.storage.Storage) UPDATE(org.folio.ActionProfile.Action.UPDATE) Logger(org.apache.logging.log4j.Logger) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) LogManager(org.apache.logging.log4j.LogManager) MappingMetadataCache(org.folio.inventory.dataimport.cache.MappingMetadataCache) MappingContext(org.folio.processing.mapping.mapper.MappingContext) HoldingsRecord(org.folio.HoldingsRecord) CompletableFuture(java.util.concurrent.CompletableFuture) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) DataImportEventPayload(org.folio.DataImportEventPayload) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 8 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class MoveApi method updateHoldings.

private void updateHoldings(RoutingContext routingContext, WebContext context, List<String> idsToUpdate, List<HoldingsRecord> holdingsToUpdate) {
    HoldingsRecordCollection storageHoldingsRecordsCollection = storage.getHoldingsRecordCollection(context);
    List<CompletableFuture<HoldingsRecord>> updateFutures = holdingsToUpdate.stream().map(storageHoldingsRecordsCollection::update).collect(Collectors.toList());
    CompletableFuture.allOf(updateFutures.toArray(new CompletableFuture[0])).handle((vVoid, throwable) -> updateFutures.stream().filter(future -> !future.isCompletedExceptionally()).map(CompletableFuture::join).map(HoldingsRecord::getId).collect(toList())).thenAccept(updatedIds -> respond(routingContext, idsToUpdate, updatedIds));
}
Also used : WebContext(org.folio.inventory.common.WebContext) ItemUtil(org.folio.inventory.support.ItemUtil) WebClient(io.vertx.ext.web.client.WebClient) URL(java.net.URL) Router(io.vertx.ext.web.Router) CompletableFuture(java.util.concurrent.CompletableFuture) Item(org.folio.inventory.domain.items.Item) RoutingContext(io.vertx.ext.web.RoutingContext) BodyHandler(io.vertx.ext.web.handler.BodyHandler) ArrayList(java.util.ArrayList) ServerErrorResponse(org.folio.inventory.support.http.server.ServerErrorResponse) JsonResponse(org.folio.inventory.support.http.server.JsonResponse) CollectionResourceClient(org.folio.inventory.storage.external.CollectionResourceClient) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) MultipleRecordsFetchClient(org.folio.inventory.storage.external.MultipleRecordsFetchClient) MoveValidator.holdingsMoveHasRequiredFields(org.folio.inventory.validation.MoveValidator.holdingsMoveHasRequiredFields) ItemCollection(org.folio.inventory.domain.items.ItemCollection) JsonObject(io.vertx.core.json.JsonObject) JsonArrayHelper.toListOfStrings(org.folio.inventory.support.JsonArrayHelper.toListOfStrings) MalformedURLException(java.net.MalformedURLException) OkapiHttpClient(org.folio.inventory.support.http.client.OkapiHttpClient) JsonResponse.unprocessableEntity(org.folio.inventory.support.http.server.JsonResponse.unprocessableEntity) JsonResponse.success(org.folio.inventory.support.http.server.JsonResponse.success) Collectors(java.util.stream.Collectors) HoldingsRecord(org.folio.HoldingsRecord) Storage(org.folio.inventory.storage.Storage) Objects(java.util.Objects) Collectors.toList(java.util.stream.Collectors.toList) MoveValidator.itemsMoveHasRequiredFields(org.folio.inventory.validation.MoveValidator.itemsMoveHasRequiredFields) List(java.util.List) ListUtils(org.apache.commons.collections15.ListUtils) HttpServerResponse(io.vertx.core.http.HttpServerResponse) ValidationError(org.folio.inventory.support.http.server.ValidationError) Optional(java.util.Optional) CqlQuery(org.folio.inventory.storage.external.CqlQuery) HttpClient(io.vertx.core.http.HttpClient) CompletableFuture(java.util.concurrent.CompletableFuture) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection)

Example 9 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class MatchHoldingEventHandlerUnitTest method shouldMatchWithSubConditionBasedOnMultiMatchResultOnHandleEventPayload.

@Test
public void shouldMatchWithSubConditionBasedOnMultiMatchResultOnHandleEventPayload(TestContext testContext) throws UnsupportedEncodingException {
    Async async = testContext.async();
    List<String> multiMatchResult = List.of(UUID.randomUUID().toString(), UUID.randomUUID().toString());
    HoldingsRecord expectedHolding = createHolding();
    doAnswer(invocation -> {
        Consumer<Success<MultipleRecords<HoldingsRecord>>> successHandler = invocation.getArgument(2);
        Success<MultipleRecords<HoldingsRecord>> result = new Success<>(new MultipleRecords<>(singletonList(expectedHolding), 1));
        successHandler.accept(result);
        return null;
    }).when(holdingCollection).findByCql(eq(format("hrid == \"%s\" AND id == (%s OR %s)", HOLDING_HRID, multiMatchResult.get(0), multiMatchResult.get(1))), any(PagingParameters.class), any(Consumer.class), any(Consumer.class));
    EventHandler eventHandler = new MatchHoldingEventHandler(mappingMetadataCache);
    HashMap<String, String> context = new HashMap<>();
    context.put(MULTI_MATCH_IDS, Json.encode(multiMatchResult));
    context.put(MAPPING_PARAMS, LOCATIONS_PARAMS);
    context.put(RELATIONS, MATCHING_RELATIONS);
    DataImportEventPayload eventPayload = createEventPayload().withContext(context);
    eventHandler.handle(eventPayload).whenComplete((processedPayload, throwable) -> {
        testContext.assertNull(throwable);
        testContext.assertEquals(1, processedPayload.getEventsChain().size());
        testContext.assertEquals(processedPayload.getEventsChain(), singletonList(DI_SRS_MARC_BIB_RECORD_CREATED.value()));
        testContext.assertEquals(DI_INVENTORY_HOLDING_MATCHED.value(), processedPayload.getEventType());
        testContext.assertEquals(Json.decodeValue(processedPayload.getContext().get(HOLDINGS.value()), HoldingsRecord.class).getId(), expectedHolding.getId());
        async.complete();
    });
}
Also used : MatchHoldingEventHandler(org.folio.inventory.dataimport.handlers.matching.MatchHoldingEventHandler) PagingParameters(org.folio.inventory.common.api.request.PagingParameters) HashMap(java.util.HashMap) EventHandler(org.folio.processing.events.services.handler.EventHandler) MatchItemEventHandler(org.folio.inventory.dataimport.handlers.matching.MatchItemEventHandler) MatchHoldingEventHandler(org.folio.inventory.dataimport.handlers.matching.MatchHoldingEventHandler) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Success(org.folio.inventory.common.domain.Success) DataImportEventPayload(org.folio.DataImportEventPayload) HoldingsRecord(org.folio.HoldingsRecord) Consumer(java.util.function.Consumer) Async(io.vertx.ext.unit.Async) MultipleRecords(org.folio.inventory.common.domain.MultipleRecords) Test(org.junit.Test)

Example 10 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class MatchHoldingEventHandlerUnitTest method shouldMatchWithSubMatchByHoldingOnHandleEventPayload.

@Test
public void shouldMatchWithSubMatchByHoldingOnHandleEventPayload(TestContext testContext) throws UnsupportedEncodingException {
    Async async = testContext.async();
    doAnswer(ans -> {
        Consumer<Success<MultipleRecords<HoldingsRecord>>> callback = ans.getArgument(2);
        Success<MultipleRecords<HoldingsRecord>> result = new Success<>(new MultipleRecords<>(singletonList(createHolding()), 1));
        callback.accept(result);
        return null;
    }).when(holdingCollection).findByCql(eq(format("hrid == \"%s\" AND id == \"%s\"", HOLDING_HRID, HOLDING_ID)), any(PagingParameters.class), any(Consumer.class), any(Consumer.class));
    EventHandler eventHandler = new MatchHoldingEventHandler(mappingMetadataCache);
    HashMap<String, String> context = new HashMap<>();
    context.put(EntityType.HOLDINGS.value(), JsonObject.mapFrom(new HoldingsRecord().withId(HOLDING_ID)).encode());
    context.put(MAPPING_PARAMS, LOCATIONS_PARAMS);
    context.put(RELATIONS, MATCHING_RELATIONS);
    DataImportEventPayload eventPayload = createEventPayload().withContext(context);
    eventHandler.handle(eventPayload).whenComplete((updatedEventPayload, throwable) -> {
        testContext.assertNull(throwable);
        testContext.assertEquals(1, updatedEventPayload.getEventsChain().size());
        testContext.assertEquals(updatedEventPayload.getEventsChain(), singletonList(DI_SRS_MARC_BIB_RECORD_CREATED.value()));
        testContext.assertEquals(DI_INVENTORY_HOLDING_MATCHED.value(), updatedEventPayload.getEventType());
        async.complete();
    });
}
Also used : MatchHoldingEventHandler(org.folio.inventory.dataimport.handlers.matching.MatchHoldingEventHandler) PagingParameters(org.folio.inventory.common.api.request.PagingParameters) HashMap(java.util.HashMap) EventHandler(org.folio.processing.events.services.handler.EventHandler) MatchItemEventHandler(org.folio.inventory.dataimport.handlers.matching.MatchItemEventHandler) MatchHoldingEventHandler(org.folio.inventory.dataimport.handlers.matching.MatchHoldingEventHandler) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Success(org.folio.inventory.common.domain.Success) DataImportEventPayload(org.folio.DataImportEventPayload) HoldingsRecord(org.folio.HoldingsRecord) Consumer(java.util.function.Consumer) Async(io.vertx.ext.unit.Async) MultipleRecords(org.folio.inventory.common.domain.MultipleRecords) Test(org.junit.Test)

Aggregations

HoldingsRecord (org.folio.HoldingsRecord)44 JsonObject (io.vertx.core.json.JsonObject)27 Test (org.junit.Test)26 DataImportEventPayload (org.folio.DataImportEventPayload)24 HashMap (java.util.HashMap)23 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)22 Record (org.folio.rest.jaxrs.model.Record)18 Success (org.folio.inventory.common.domain.Success)17 Consumer (java.util.function.Consumer)14 ParsedRecord (org.folio.rest.jaxrs.model.ParsedRecord)14 PagingParameters (org.folio.inventory.common.api.request.PagingParameters)13 Context (org.folio.inventory.common.Context)12 MultipleRecords (org.folio.inventory.common.domain.MultipleRecords)12 EventHandler (org.folio.processing.events.services.handler.EventHandler)11 MappingParameters (org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters)11 Async (io.vertx.ext.unit.Async)8 MappingMetadataDto (org.folio.MappingMetadataDto)8 MatchItemEventHandler (org.folio.inventory.dataimport.handlers.matching.MatchItemEventHandler)8 HoldingsRecordCollection (org.folio.inventory.domain.HoldingsRecordCollection)8 Before (org.junit.Before)8