diff --git a/mod-source-record-manager-server/src/main/java/org/folio/services/journal/JournalUtil.java b/mod-source-record-manager-server/src/main/java/org/folio/services/journal/JournalUtil.java index 0787270d5..0de408a81 100644 --- a/mod-source-record-manager-server/src/main/java/org/folio/services/journal/JournalUtil.java +++ b/mod-source-record-manager-server/src/main/java/org/folio/services/journal/JournalUtil.java @@ -26,8 +26,6 @@ import static org.apache.commons.lang3.StringUtils.isEmpty; import static org.folio.rest.jaxrs.model.DataImportEventTypes.DI_ERROR; import static org.folio.rest.jaxrs.model.DataImportEventTypes.DI_INVENTORY_INSTANCE_CREATED; -import static org.folio.rest.jaxrs.model.DataImportEventTypes.DI_LOG_SRS_MARC_BIB_RECORD_UPDATED; -import static org.folio.rest.jaxrs.model.DataImportEventTypes.DI_SRS_MARC_BIB_RECORD_UPDATED; import static org.folio.rest.jaxrs.model.JournalRecord.EntityType.AUTHORITY; import static org.folio.rest.jaxrs.model.JournalRecord.EntityType.HOLDINGS; import static org.folio.rest.jaxrs.model.JournalRecord.EntityType.INSTANCE; @@ -144,8 +142,7 @@ record = Json.decodeValue(recordAsString, Record.class); } if (!isEmpty(entityAsString)) { - if (entityType == INSTANCE || entityType == PO_LINE || entityType == AUTHORITY || - (entityType == MARC_BIBLIOGRAPHIC && isMarcBibUpdateEventReceived(eventPayload))) { + if (entityType == INSTANCE || entityType == PO_LINE || entityType == AUTHORITY || entityType == MARC_BIBLIOGRAPHIC) { JsonObject entityJson = new JsonObject(entityAsString); journalRecord.setEntityId(entityJson.getString(ID_KEY)); if (entityType == INSTANCE || entityType == PO_LINE) { @@ -187,16 +184,6 @@ record = Json.decodeValue(recordAsString, Record.class); } } - private static boolean isMarcBibUpdateEventReceived(DataImportEventPayload eventPayload) { - if (DI_LOG_SRS_MARC_BIB_RECORD_UPDATED == DataImportEventTypes.fromValue(eventPayload.getEventType()) - || DI_SRS_MARC_BIB_RECORD_UPDATED == DataImportEventTypes.fromValue(eventPayload.getEventType())) { - return true; - } - return eventPayload.getEventsChain().stream() - .reduce((first, second) -> second) - .map(mp -> DI_SRS_MARC_BIB_RECORD_UPDATED == DataImportEventTypes.fromValue(mp)).orElse(false); - } - private static JournalRecord buildJournalRecordWithMarcBibType(JournalRecord.ActionStatus actionStatus, JournalRecord.ActionType actionType, Record currentRecord, DataImportEventPayload eventPayload, HashMap eventPayloadContext) { String marcBibEntityAsString = eventPayloadContext.get(MARC_BIBLIOGRAPHIC.value()); diff --git a/mod-source-record-manager-server/src/main/java/org/folio/verticle/consumers/StoredRecordChunksKafkaHandler.java b/mod-source-record-manager-server/src/main/java/org/folio/verticle/consumers/StoredRecordChunksKafkaHandler.java index 0a48712a5..b57594ad7 100644 --- a/mod-source-record-manager-server/src/main/java/org/folio/verticle/consumers/StoredRecordChunksKafkaHandler.java +++ b/mod-source-record-manager-server/src/main/java/org/folio/verticle/consumers/StoredRecordChunksKafkaHandler.java @@ -43,7 +43,6 @@ import java.util.stream.Collectors; import static java.lang.String.format; -import static org.apache.commons.lang3.ObjectUtils.allNotNull; import static org.folio.rest.jaxrs.model.DataImportEventTypes.DI_INCOMING_EDIFACT_RECORD_PARSED; import static org.folio.rest.jaxrs.model.DataImportEventTypes.DI_MARC_BIB_FOR_ORDER_CREATED; import static org.folio.rest.jaxrs.model.DataImportEventTypes.DI_SRS_MARC_AUTHORITY_RECORD_CREATED; @@ -56,6 +55,7 @@ import static org.folio.rest.jaxrs.model.Record.RecordType.MARC_BIB; import static org.folio.rest.jaxrs.model.Record.RecordType.MARC_HOLDING; import static org.folio.verticle.consumers.util.JobExecutionUtils.isNeedToSkip; +import static org.folio.verticle.consumers.util.MarcImportEventsHandler.NO_TITLE_MESSAGE; @Component @Qualifier("StoredRecordChunksKafkaHandler") @@ -217,6 +217,9 @@ private JsonArray buildJournalRecords(List storedRecords, Optional storedRecords, Optional populateRecordTitleIfNeeded(JournalRecord journalR return titleExtractor.apply(parsedRecord, mappingRules); }) - .map(title -> Future.succeededFuture(journalRecord.withTitle(title))) + .map(title -> { + if (title.isEmpty() || title == null) { + title = NO_TITLE_MESSAGE; + } + return Future.succeededFuture(journalRecord.withTitle(title)); + }) .orElseGet(() -> Future.succeededFuture(journalRecord))); } } diff --git a/mod-source-record-manager-server/src/main/resources/templates/db_scripts/create_get_job_execution_summary_function.sql b/mod-source-record-manager-server/src/main/resources/templates/db_scripts/create_get_job_execution_summary_function.sql index 3f9d30bc9..4a1eda5bd 100644 --- a/mod-source-record-manager-server/src/main/resources/templates/db_scripts/create_get_job_execution_summary_function.sql +++ b/mod-source-record-manager-server/src/main/resources/templates/db_scripts/create_get_job_execution_summary_function.sql @@ -52,11 +52,12 @@ BEGIN COUNT(DISTINCT(source_id)) FILTER (WHERE entity_type = 'INVOICE' AND ((action_type = 'NON_MATCH' AND action_type_max = 'NON_MATCH') OR action_status = 'ERROR')) AS total_discarded_invoices, COUNT(DISTINCT(source_id)) FILTER (WHERE entity_type = 'INVOICE' AND action_status = 'ERROR') AS total_invoices_errors FROM journal_records - INNER JOIN (SELECT entity_id as entity_id_max, entity_type as entity_type_max, action_status as action_status_max,(array_agg(id ORDER BY array_position(array['CREATE', 'UPDATE', 'MODIFY', 'NON_MATCH'], action_type)))[1] as id + INNER JOIN (SELECT entity_id as entity_id_max, entity_type as entity_type_max, action_status as action_status_max,(array_agg(id ORDER BY array_position(array['CREATE', 'UPDATE', 'MODIFY', 'NON_MATCH'], action_type)))[1] as id, + source_id as temp_source_id FROM journal_records WHERE journal_records.job_execution_id = job_id - GROUP BY entity_id, entity_type, action_status) AS actions - ON actions.id = journal_records.id + GROUP BY source_id, entity_id, entity_type, action_status) AS actions + ON actions.id = journal_records.id AND actions.temp_source_id = journal_records.source_id INNER JOIN (SELECT (array_agg(action_type ORDER BY array_position(array['CREATE', 'UPDATE', 'MODIFY', 'NON_MATCH'], action_type)))[1] as action_type_max, source_id as source_id_max, entity_type as entity_type_max FROM journal_records WHERE journal_records.job_execution_id = job_id diff --git a/mod-source-record-manager-server/src/test/java/org/folio/rest/impl/metadataProvider/MetadataProviderJobExecutionAPITest.java b/mod-source-record-manager-server/src/test/java/org/folio/rest/impl/metadataProvider/MetadataProviderJobExecutionAPITest.java index f0542be2c..51877dc15 100644 --- a/mod-source-record-manager-server/src/test/java/org/folio/rest/impl/metadataProvider/MetadataProviderJobExecutionAPITest.java +++ b/mod-source-record-manager-server/src/test/java/org/folio/rest/impl/metadataProvider/MetadataProviderJobExecutionAPITest.java @@ -1431,6 +1431,288 @@ public void shouldReturnOneUpdatedSourceRecordWhenRecordWasModifiedAndUpdated(Te })); } + @Test + public void shouldReturnMultipleDiscardedMarcBib(TestContext context) { + Async async = context.async(); + JobExecution createdJobExecution = constructAndPostInitJobExecutionRqDto(1).getJobExecutions().get(0); + String recordTitle = "test title"; + + Future future = Future.succeededFuture() + .compose(v -> createJournalRecord(createdJobExecution.getId(), UUID.randomUUID().toString(), null, null, recordTitle,0, CREATE, MARC_BIBLIOGRAPHIC, ERROR, "error")) + .compose(v -> createJournalRecord(createdJobExecution.getId(), UUID.randomUUID().toString(), null, null, recordTitle, 0, CREATE, MARC_BIBLIOGRAPHIC, ERROR, "error")) + .onFailure(context::fail); + + future.onComplete(ar -> context.verify(v -> { + RestAssured.given() + .spec(spec) + .get(GET_JOB_EXECUTION_SUMMARY_PATH + "/" + createdJobExecution.getId()) + .then() + .statusCode(HttpStatus.SC_OK) + .body("sourceRecordSummary.totalCreatedEntities", is(0)) + .body("sourceRecordSummary.totalUpdatedEntities", is(0)) + .body("sourceRecordSummary.totalDiscardedEntities", is(2)) + .body("sourceRecordSummary.totalErrors", is(2)) + .body("totalErrors", is(2)); + + async.complete(); + })); + } + + @Test + public void shouldReturnMultipleErrorInstances(TestContext context) { + Async async = context.async(); + JobExecution createdJobExecution = constructAndPostInitJobExecutionRqDto(1).getJobExecutions().get(0); + String[] sourceRecordIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String errMessage = "error"; + + Future future = Future.succeededFuture() + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], null, null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], null, null, null, 0, CREATE, INSTANCE, ERROR, errMessage)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], null, null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], null, null, null, 0, CREATE, INSTANCE, ERROR, errMessage)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], null, null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], null, null, null, 0, CREATE, INSTANCE, ERROR, errMessage)) + + + .onFailure(context::fail); + + future.onComplete(ar -> context.verify(v -> { + RestAssured.given() + .spec(spec) + .when() + .get(GET_JOB_EXECUTION_SUMMARY_PATH + "/" + createdJobExecution.getId()) + .then() + .statusCode(HttpStatus.SC_OK) + .body("sourceRecordSummary.totalCreatedEntities", is(3)) + .body("sourceRecordSummary.totalUpdatedEntities", is(0)) + .body("sourceRecordSummary.totalDiscardedEntities", is(0)) + .body("sourceRecordSummary.totalErrors", is(0)) + .body("instanceSummary.totalCreatedEntities", is(0)) + .body("instanceSummary.totalUpdatedEntities", is(0)) + .body("instanceSummary.totalDiscardedEntities", is(3)) + .body("instanceSummary.totalErrors", is(3)) + .body("totalErrors", is(3)); + + async.complete(); + })); + } + + @Test + public void shouldReturnMultipleErrorHoldings(TestContext context) { + Async async = context.async(); + JobExecution createdJobExecution = constructAndPostInitJobExecutionRqDto(1).getJobExecutions().get(0); + String[] sourceRecordIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] marcBibEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] instanceEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String errMessage = "error"; + + Future future = Future.succeededFuture() + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], marcBibEntityIds[0], null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], instanceEntityIds[0], null, null, 0, CREATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], null, null, null, 0, CREATE, HOLDINGS, ERROR, errMessage)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], marcBibEntityIds[1], null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], instanceEntityIds[1], null, null, 0, CREATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], null, null, null, 0, CREATE, HOLDINGS, ERROR, errMessage)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], marcBibEntityIds[2], null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], instanceEntityIds[2], null, null, 0, CREATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], null, null, null, 0, CREATE, HOLDINGS, ERROR, errMessage)) + + .onFailure(context::fail); + + future.onComplete(ar -> context.verify(v -> { + RestAssured.given() + .spec(spec) + .when() + .get(GET_JOB_EXECUTION_SUMMARY_PATH + "/" + createdJobExecution.getId()) + .then() + .log().all() + .statusCode(HttpStatus.SC_OK) + .body("sourceRecordSummary.totalCreatedEntities", is(3)) + .body("sourceRecordSummary.totalUpdatedEntities", is(0)) + .body("sourceRecordSummary.totalDiscardedEntities", is(0)) + .body("sourceRecordSummary.totalErrors", is(0)) + .body("instanceSummary.totalCreatedEntities", is(3)) + .body("instanceSummary.totalUpdatedEntities", is(0)) + .body("instanceSummary.totalDiscardedEntities", is(0)) + .body("instanceSummary.totalErrors", is(0)) + .body("holdingSummary.totalCreatedEntities", is(0)) + .body("holdingSummary.totalUpdatedEntities", is(0)) + .body("holdingSummary.totalDiscardedEntities", is(3)) + .body("holdingSummary.totalErrors", is(3)) + .body("totalErrors", is(3)); + + async.complete(); + })); + } + + @Test + public void shouldReturnMultipleErrorItems(TestContext context) { + Async async = context.async(); + JobExecution createdJobExecution = constructAndPostInitJobExecutionRqDto(1).getJobExecutions().get(0); + String[] sourceRecordIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] marcBibEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] instanceEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] holdingsEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + + String errMessage = "error"; + + Future future = Future.succeededFuture() + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], marcBibEntityIds[0], null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], instanceEntityIds[0], null, null, 0, CREATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], holdingsEntityIds[0], null, null, 0, CREATE, HOLDINGS, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], null, null, null, 0, CREATE, ITEM, ERROR, errMessage)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], marcBibEntityIds[1], null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], instanceEntityIds[1], null, null, 0, CREATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], holdingsEntityIds[1], null, null, 0, CREATE, HOLDINGS, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], null, null, null, 0, CREATE, ITEM, ERROR, errMessage)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], marcBibEntityIds[2], null, null, 0, CREATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], instanceEntityIds[2], null, null, 0, CREATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], holdingsEntityIds[2], null, null, 0, CREATE, HOLDINGS, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], null, null, null, 0, CREATE, ITEM, ERROR, errMessage)) + + .onFailure(context::fail); + + future.onComplete(ar -> context.verify(v -> { + RestAssured.given() + .spec(spec) + .when() + .get(GET_JOB_EXECUTION_SUMMARY_PATH + "/" + createdJobExecution.getId()) + .then() + .log().all() + .statusCode(HttpStatus.SC_OK) + .body("sourceRecordSummary.totalCreatedEntities", is(3)) + .body("sourceRecordSummary.totalUpdatedEntities", is(0)) + .body("sourceRecordSummary.totalDiscardedEntities", is(0)) + .body("sourceRecordSummary.totalErrors", is(0)) + .body("instanceSummary.totalCreatedEntities", is(3)) + .body("instanceSummary.totalUpdatedEntities", is(0)) + .body("instanceSummary.totalDiscardedEntities", is(0)) + .body("instanceSummary.totalErrors", is(0)) + .body("holdingSummary.totalCreatedEntities", is(3)) + .body("holdingSummary.totalUpdatedEntities", is(0)) + .body("holdingSummary.totalDiscardedEntities", is(0)) + .body("holdingSummary.totalErrors", is(0)) + .body("itemSummary.totalCreatedEntities", is(0)) + .body("itemSummary.totalUpdatedEntities", is(0)) + .body("itemSummary.totalDiscardedEntities", is(3)) + .body("itemSummary.totalErrors", is(3)) + .body("totalErrors", is(3)); + + async.complete(); + })); + } + + @Test + public void shouldReturnMultipleDiscardedHoldings(TestContext context) { + Async async = context.async(); + JobExecution createdJobExecution = constructAndPostInitJobExecutionRqDto(1).getJobExecutions().get(0); + String[] sourceRecordIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] marcBibEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] instanceEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + + Future future = Future.succeededFuture() + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], marcBibEntityIds[0], null, null, 1, UPDATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], instanceEntityIds[0], null, null, 2, UPDATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], null, null, null, 3, NON_MATCH, HOLDINGS, COMPLETED, null)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], marcBibEntityIds[1], null, null, 4, UPDATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], instanceEntityIds[1], null, null, 5, UPDATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], null, null, null, 6, NON_MATCH, HOLDINGS, COMPLETED, null)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], marcBibEntityIds[2], null, null, 7, UPDATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], instanceEntityIds[2], null, null, 8, UPDATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], null, null, null, 9, NON_MATCH, HOLDINGS, COMPLETED, null)) + + .onFailure(context::fail); + + future.onComplete(ar -> context.verify(v -> { + RestAssured.given() + .spec(spec) + .when() + .get(GET_JOB_EXECUTION_SUMMARY_PATH + "/" + createdJobExecution.getId()) + .then() + .log().all() + .statusCode(HttpStatus.SC_OK) + .body("sourceRecordSummary.totalCreatedEntities", is(0)) + .body("sourceRecordSummary.totalUpdatedEntities", is(3)) + .body("sourceRecordSummary.totalDiscardedEntities", is(0)) + .body("sourceRecordSummary.totalErrors", is(0)) + .body("instanceSummary.totalCreatedEntities", is(0)) + .body("instanceSummary.totalUpdatedEntities", is(3)) + .body("instanceSummary.totalDiscardedEntities", is(0)) + .body("instanceSummary.totalErrors", is(0)) + .body("holdingSummary.totalCreatedEntities", is(0)) + .body("holdingSummary.totalUpdatedEntities", is(0)) + .body("holdingSummary.totalDiscardedEntities", is(3)) + .body("holdingSummary.totalErrors", is(0)) + .body("totalErrors", is(0)); + + async.complete(); + })); + } + + @Test + public void shouldReturnMultipleDiscardedHoldingsAndItems(TestContext context) { + Async async = context.async(); + JobExecution createdJobExecution = constructAndPostInitJobExecutionRqDto(1).getJobExecutions().get(0); + String[] sourceRecordIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] marcBibEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + String[] instanceEntityIds = {UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()}; + + Future future = Future.succeededFuture() + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], marcBibEntityIds[0], null, null, 1, UPDATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], instanceEntityIds[0], null, null, 2, UPDATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], null, null, null, 3, NON_MATCH, HOLDINGS, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[0], null, null, null, 4, NON_MATCH, ITEM, COMPLETED, null)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], marcBibEntityIds[1], null, null, 5, UPDATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], instanceEntityIds[1], null, null, 6, UPDATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], null, null, null, 7, NON_MATCH, HOLDINGS, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[1], null, null, null, 8, NON_MATCH, ITEM, COMPLETED, null)) + + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], marcBibEntityIds[2], null, null, 9, UPDATE, MARC_BIBLIOGRAPHIC, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], instanceEntityIds[2], null, null, 10, UPDATE, INSTANCE, COMPLETED, null)) + .compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], null, null, null, 11, NON_MATCH, HOLDINGS, COMPLETED, null)) +.compose(v -> createJournalRecord(createdJobExecution.getId(), sourceRecordIds[2], null, null, null, 12, NON_MATCH, ITEM, COMPLETED, null)) + + .onFailure(context::fail); + + future.onComplete(ar -> context.verify(v -> { + RestAssured.given() + .spec(spec) + .when() + .get(GET_JOB_EXECUTION_SUMMARY_PATH + "/" + createdJobExecution.getId()) + .then() + .log().all() + .statusCode(HttpStatus.SC_OK) + .body("sourceRecordSummary.totalCreatedEntities", is(0)) + .body("sourceRecordSummary.totalUpdatedEntities", is(3)) + .body("sourceRecordSummary.totalDiscardedEntities", is(0)) + .body("sourceRecordSummary.totalErrors", is(0)) + .body("instanceSummary.totalCreatedEntities", is(0)) + .body("instanceSummary.totalUpdatedEntities", is(3)) + .body("instanceSummary.totalDiscardedEntities", is(0)) + .body("instanceSummary.totalErrors", is(0)) + .body("holdingSummary.totalCreatedEntities", is(0)) + .body("holdingSummary.totalUpdatedEntities", is(0)) + .body("holdingSummary.totalDiscardedEntities", is(3)) + .body("holdingSummary.totalErrors", is(0)) + .body("itemSummary.totalCreatedEntities", is(0)) + .body("itemSummary.totalUpdatedEntities", is(0)) + .body("itemSummary.totalDiscardedEntities", is(3)) + .body("itemSummary.totalErrors", is(0)) + .body("totalErrors", is(0)); + + async.complete(); + })); + } + @Test public void shouldReturnNotFoundWhenHasNoJobExecution() { RestAssured.given()