Search in sources :

Example 1 with UPDATE

use of org.folio.ActionProfile.Action.UPDATE 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 2 with UPDATE

use of org.folio.ActionProfile.Action.UPDATE in project mod-inventory by folio-org.

the class UpdateHoldingEventHandler method processOLError.

private void processOLError(DataImportEventPayload dataImportEventPayload, CompletableFuture<DataImportEventPayload> future, HoldingsRecordCollection holdingsRecords, HoldingsRecord holding, Failure failure) {
    int currentRetryNumber = dataImportEventPayload.getContext().get(CURRENT_RETRY_NUMBER) == null ? 0 : Integer.parseInt(dataImportEventPayload.getContext().get(CURRENT_RETRY_NUMBER));
    if (currentRetryNumber < MAX_RETRIES_COUNT) {
        dataImportEventPayload.getContext().put(CURRENT_RETRY_NUMBER, String.valueOf(currentRetryNumber + 1));
        LOGGER.warn("Error updating Holding by id '{}' - '{}', status code '{}'. Retry UpdateHoldingEventHandler handler...", holding.getId(), failure.getReason(), failure.getStatusCode());
        holdingsRecords.findById(holding.getId()).thenAccept(actualInstance -> prepareDataAndReInvokeCurrentHandler(dataImportEventPayload, future, actualInstance)).exceptionally(e -> {
            dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
            String errMessage = format("Cannot get actual Holding by id: '%s' for jobExecutionId '%s'. Error: %s ", holding.getId(), dataImportEventPayload.getJobExecutionId(), e.getCause());
            LOGGER.error(errMessage);
            future.completeExceptionally(new EventProcessingException(errMessage));
            return null;
        });
    } else {
        dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
        String errMessage = format("Current retry number %s exceeded or equal given number %s for the Holding update for jobExecutionId '%s' ", MAX_RETRIES_COUNT, currentRetryNumber, dataImportEventPayload.getJobExecutionId());
        LOGGER.error(errMessage);
        future.completeExceptionally(new EventProcessingException(errMessage));
    }
}
Also used : 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) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 3 with UPDATE

use of org.folio.ActionProfile.Action.UPDATE in project mod-inventory by folio-org.

the class UpdateItemEventHandler method handle.

@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
    CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
    try {
        dataImportEventPayload.setEventType(DI_INVENTORY_ITEM_UPDATED.value());
        HashMap<String, String> payloadContext = dataImportEventPayload.getContext();
        if (isNull(payloadContext) || isBlank(payloadContext.get(MARC_BIBLIOGRAPHIC.value())) || isBlank(payloadContext.get(ITEM.value()))) {
            LOG.error(PAYLOAD_HAS_NO_DATA_MSG);
            return CompletableFuture.failedFuture(new EventProcessingException(PAYLOAD_HAS_NO_DATA_MSG));
        }
        if (dataImportEventPayload.getCurrentNode().getChildSnapshotWrappers().isEmpty()) {
            LOG.error(ACTION_HAS_NO_MAPPING_MSG);
            return CompletableFuture.failedFuture(new EventProcessingException(ACTION_HAS_NO_MAPPING_MSG));
        }
        LOG.info("Processing UpdateItemEventHandler starting with jobExecutionId: {}.", dataImportEventPayload.getJobExecutionId());
        AtomicBoolean isProtectedStatusChanged = new AtomicBoolean();
        Context context = EventHandlingUtil.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_MSG, jobExecutionId, recordId, chunkId)))).compose(mappingMetadataDto -> {
            String oldItemStatus = preparePayloadAndGetStatus(dataImportEventPayload, payloadContext, mappingMetadataDto);
            JsonObject mappedItemAsJson = new JsonObject(payloadContext.get(ITEM.value()));
            mappedItemAsJson = mappedItemAsJson.containsKey(ITEM_PATH_FIELD) ? mappedItemAsJson.getJsonObject(ITEM_PATH_FIELD) : mappedItemAsJson;
            List<String> errors = validateItem(mappedItemAsJson, requiredFields);
            if (!errors.isEmpty()) {
                String msg = format("Mapped Instance is invalid: %s, by jobExecutionId: '%s' and recordId: '%s' and chunkId: '%s' ", errors, jobExecutionId, recordId, chunkId);
                LOG.error(msg);
                return Future.failedFuture(msg);
            }
            String newItemStatus = mappedItemAsJson.getJsonObject(STATUS_KEY).getString("name");
            isProtectedStatusChanged.set(isProtectedStatusChanged(oldItemStatus, newItemStatus));
            if (isProtectedStatusChanged.get()) {
                mappedItemAsJson.getJsonObject(STATUS_KEY).put("name", oldItemStatus);
            }
            ItemCollection itemCollection = storage.getItemCollection(context);
            Item itemToUpdate = ItemUtil.jsonToItem(mappedItemAsJson);
            return verifyItemBarcodeUniqueness(itemToUpdate, itemCollection).compose(v -> updateItemAndRetryIfOLExists(itemToUpdate, itemCollection, dataImportEventPayload)).onSuccess(updatedItem -> {
                if (isProtectedStatusChanged.get()) {
                    String msg = String.format(STATUS_UPDATE_ERROR_MSG, oldItemStatus, newItemStatus);
                    LOG.warn(msg);
                    dataImportEventPayload.getContext().put(ITEM.value(), ItemUtil.mapToJson(updatedItem).encode());
                    future.completeExceptionally(new EventProcessingException(msg));
                } else {
                    addHoldingToPayloadIfNeeded(dataImportEventPayload, context, updatedItem).onComplete(item -> {
                        dataImportEventPayload.getContext().put(ITEM.value(), ItemUtil.mapToJson(updatedItem).encode());
                        future.complete(dataImportEventPayload);
                    });
                }
            });
        }).onFailure(e -> {
            LOG.error("Failed to update inventory Item by jobExecutionId: '{}' and recordId: '{}' and chunkId: '{}' ", jobExecutionId, recordId, chunkId, e);
            future.completeExceptionally(e);
        });
    } catch (Exception e) {
        LOG.error("Error updating inventory Item", e);
        future.completeExceptionally(e);
    }
    return future;
}
Also used : Context(org.folio.inventory.common.Context) MappingContext(org.folio.processing.mapping.mapper.MappingContext) Arrays(java.util.Arrays) MappingMetadataDto(org.folio.MappingMetadataDto) EventHandler(org.folio.processing.events.services.handler.EventHandler) ItemUtil(org.folio.inventory.support.ItemUtil) JsonHelper(org.folio.inventory.support.JsonHelper) ZonedDateTime(java.time.ZonedDateTime) HttpStatus(org.apache.http.HttpStatus) Failure(org.folio.inventory.common.domain.Failure) Item(org.folio.inventory.domain.items.Item) ACTION_PROFILE(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.ACTION_PROFILE) StringUtils(org.apache.commons.lang3.StringUtils) ITEM(org.folio.rest.jaxrs.model.EntityType.ITEM) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) ProfileSnapshotWrapper(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper) ObjectMapperTool(org.folio.dbschema.ObjectMapperTool) Objects.isNull(java.util.Objects.isNull) ItemCollection(org.folio.inventory.domain.items.ItemCollection) JsonObject(io.vertx.core.json.JsonObject) ZoneOffset(java.time.ZoneOffset) StringUtils.isEmpty(org.apache.commons.lang3.StringUtils.isEmpty) DataImportEventPayload(org.folio.DataImportEventPayload) Set(java.util.Set) UUID(java.util.UUID) Future(io.vertx.core.Future) String.format(java.lang.String.format) Storage(org.folio.inventory.storage.Storage) List(java.util.List) Logger(org.apache.logging.log4j.Logger) EventHandlingUtil(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil) UnsupportedEncodingException(java.io.UnsupportedEncodingException) PagingParameters(org.folio.inventory.common.api.request.PagingParameters) Context(org.folio.inventory.common.Context) Json(io.vertx.core.json.Json) MappingManager(org.folio.processing.mapping.MappingManager) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) DI_INVENTORY_ITEM_UPDATED(org.folio.DataImportEventTypes.DI_INVENTORY_ITEM_UPDATED) HashSet(java.util.HashSet) MARC_BIBLIOGRAPHIC(org.folio.rest.jaxrs.model.EntityType.MARC_BIBLIOGRAPHIC) ActionProfile(org.folio.ActionProfile) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) MappingContext(org.folio.processing.mapping.mapper.MappingContext) HOLDINGS(org.folio.rest.jaxrs.model.EntityType.HOLDINGS) ItemStatusName(org.folio.inventory.domain.items.ItemStatusName) CqlHelper(org.folio.inventory.support.CqlHelper) Promise(io.vertx.core.Promise) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) UPDATE(org.folio.ActionProfile.Action.UPDATE) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) StringUtils.isBlank(org.apache.commons.lang3.StringUtils.isBlank) STATUS_KEY(org.folio.inventory.domain.items.Item.STATUS_KEY) DateTimeFormatter(java.time.format.DateTimeFormatter) LogManager(org.apache.logging.log4j.LogManager) MappingMetadataCache(org.folio.inventory.dataimport.cache.MappingMetadataCache) JsonObject(io.vertx.core.json.JsonObject) ItemCollection(org.folio.inventory.domain.items.ItemCollection) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) DataImportEventPayload(org.folio.DataImportEventPayload) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Item(org.folio.inventory.domain.items.Item) CompletableFuture(java.util.concurrent.CompletableFuture) List(java.util.List) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Aggregations

JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)3 Json (io.vertx.core.json.Json)3 JsonObject (io.vertx.core.json.JsonObject)3 String.format (java.lang.String.format)3 HashMap (java.util.HashMap)3 Objects.isNull (java.util.Objects.isNull)3 CompletableFuture (java.util.concurrent.CompletableFuture)3 StringUtils (org.apache.commons.lang3.StringUtils)3 StringUtils.isEmpty (org.apache.commons.lang3.StringUtils.isEmpty)3 HttpStatus (org.apache.http.HttpStatus)3 LogManager (org.apache.logging.log4j.LogManager)3 Logger (org.apache.logging.log4j.Logger)3 ActionProfile (org.folio.ActionProfile)3 UPDATE (org.folio.ActionProfile.Action.UPDATE)3 DataImportEventPayload (org.folio.DataImportEventPayload)3 ObjectMapperTool (org.folio.dbschema.ObjectMapperTool)3 Context (org.folio.inventory.common.Context)3 Failure (org.folio.inventory.common.domain.Failure)3 MappingMetadataCache (org.folio.inventory.dataimport.cache.MappingMetadataCache)3 HoldingsRecordCollection (org.folio.inventory.domain.HoldingsRecordCollection)3