Skip to content

Commit

Permalink
Merge branch 'master' into README-AUTHORITY_EXTENDED
Browse files Browse the repository at this point in the history
  • Loading branch information
julianladisch authored Feb 21, 2025
2 parents 2e1a77c + abe01d1 commit e3dfeff
Show file tree
Hide file tree
Showing 14 changed files with 456 additions and 110 deletions.
5 changes: 4 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
## 21.1.0-SNAPSHOT 2024-xx-xx
## 21.1.0-SNAPSHOT 2025-xx-xx
* Provide consistent handling with concurrency two or more Marc Bib Update events for the same bib record [MODINV-1100](https://folio-org.atlassian.net/browse/MODINV-1100)
* Enable system user for data-import processes [MODINV-1115](https://folio-org.atlassian.net/browse/MODINV-1115)
* Missing x-okapi-user-id header in communications with inventory-storage [MODINV-1134](https://folio-org.atlassian.net/browse/MODINV-1134)
* Fix handling optimistic locking behavior for instance update when consuming Marc Bib update event [MODINV-1125](https://folio-org.atlassian.net/browse/MODINV-1125)
* Replace usage of deprecated instance-storage-batch API [MODINV-1101](https://folio-org.atlassian.net/browse/MODINV-1101Л)
* Update the snapshot status from PROCESSING_FINISHED to COMMITTED in the InstanceIngressEventHandler [MODINV-1161](https://folio-org.atlassian.net/browse/MODINV-1161)
* Add "deleted" field to Instance schema [MODINVSTOR-1342](https://folio-org.atlassian.net/browse/MODINVSTOR-1342)
* Adjust /mark-deleted endpoint behavior to set the "deleted" flag [MODINV-1138](https://folio-org.atlassian.net/browse/MODINV-1138)
* Implement marc bib submatch [MODINV-1114](https://issues.folio.org/browse/MODINV-1114)

## 21.0.0 2024-10-29
* Existing "035" field is not retained the original position in imported record [MODINV-1049](https://folio-org.atlassian.net/browse/MODINV-1049)
Expand Down
4 changes: 2 additions & 2 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"provides": [
{
"id": "inventory",
"version": "14.0",
"version": "14.1",
"handlers": [
{
"methods": ["GET"],
Expand Down Expand Up @@ -619,7 +619,7 @@
},
{
"id": "instance-storage",
"version": "11.0"
"version": "11.1"
},
{
"id": "instance-storage-batch-sync",
Expand Down
4 changes: 4 additions & 0 deletions ramls/instance.json
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,10 @@
"type": "boolean",
"description": "Records the fact that the record should not be displayed in a discovery system"
},
"deleted": {
"type": "boolean",
"description": "Indicates whether the record was marked for deletion"
},
"statisticalCodeIds": {
"type": "array",
"description": "List of statistical code IDs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ private Future<Instance> updateSuppressFromDiscoveryFlagIfNeeded(Instance target
private Instance populateTargetInstanceWithNonMarcControlledFields(Instance targetInstance, Instance sourceInstance) {
targetInstance.setStaffSuppress(sourceInstance.getStaffSuppress());
targetInstance.setDiscoverySuppress(sourceInstance.getDiscoverySuppress());
targetInstance.setDeleted(sourceInstance.getDeleted());
targetInstance.setCatalogedDate(sourceInstance.getCatalogedDate());
targetInstance.setStatusId(sourceInstance.getStatusId());
targetInstance.setStatisticalCodeIds(sourceInstance.getStatisticalCodeIds());
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.vertx.core.json.Json;
import org.folio.DataImportEventPayload;
import org.folio.HoldingsRecord;
import org.folio.MatchProfile;
import org.folio.inventory.common.Context;
import org.folio.inventory.common.api.request.PagingParameters;
import org.folio.inventory.consortium.services.ConsortiumService;
Expand All @@ -15,11 +16,13 @@
import org.folio.inventory.domain.HoldingsRecordCollection;
import org.folio.inventory.domain.instances.InstanceCollection;
import org.folio.inventory.storage.Storage;
import org.folio.rest.jaxrs.model.EntityType;
import org.folio.rest.jaxrs.model.Record;
import org.folio.rest.jaxrs.model.RecordMatchingDto;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Optional;

import static java.lang.String.format;
import static org.apache.commons.lang3.StringUtils.isBlank;
Expand Down Expand Up @@ -63,9 +66,16 @@ protected String getMultiMatchResultKey() {
}

@Override
protected Future<Void> ensureRelatedEntities(List<Record> records, DataImportEventPayload eventPayload) {
if (records.size() == 1) {
Record matchedRecord = records.get(0);
protected boolean canSubMatchProfileProcessMultiMatchResult(MatchProfile matchProfile) {
return matchProfile.getExistingRecordType() == EntityType.MARC_BIBLIOGRAPHIC
|| matchProfile.getExistingRecordType() == EntityType.INSTANCE
|| matchProfile.getExistingRecordType() == EntityType.HOLDINGS;
}

@Override
protected Future<Void> ensureRelatedEntities(Optional<Record> recordOptional, DataImportEventPayload eventPayload) {
if (recordOptional.isPresent()) {
Record matchedRecord = recordOptional.get();
String instanceId = ParsedRecordUtil.getAdditionalSubfieldValue(matchedRecord.getParsedRecord(), AdditionalSubfields.I);
String matchedRecordTenantId = getTenant(eventPayload);
Context context = EventHandlingUtil.constructContext(matchedRecordTenantId, eventPayload.getToken(), eventPayload.getOkapiUrl(),
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/folio/inventory/domain/instances/Instance.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class Instance {
public static final String PREVIOUSLY_HELD_KEY = "previouslyHeld";
public static final String STAFF_SUPPRESS_KEY = "staffSuppress";
public static final String DISCOVERY_SUPPRESS_KEY = "discoverySuppress";
public static final String DELETED_KEY = "deleted";
public static final String STATISTICAL_CODE_IDS_KEY = "statisticalCodeIds";
public static final String ADMININSTRATIVE_NOTES_KEY = "administrativeNotes";
public static final String SOURCE_RECORD_FORMAT_KEY = "sourceRecordFormat";
Expand Down Expand Up @@ -109,6 +110,7 @@ public class Instance {
private Boolean previouslyHeld;
private Boolean staffSuppress;
private Boolean discoverySuppress;
private Boolean deleted;
private List<String> statisticalCodeIds = new ArrayList<>();
private String sourceRecordFormat;
private String statusId;
Expand Down Expand Up @@ -182,6 +184,7 @@ public static Instance fromJson(JsonObject instanceJson) {
.setPreviouslyHeld(instanceJson.getBoolean(PREVIOUSLY_HELD_KEY, false))
.setStaffSuppress(instanceJson.getBoolean(STAFF_SUPPRESS_KEY, false))
.setDiscoverySuppress(instanceJson.getBoolean(DISCOVERY_SUPPRESS_KEY, false))
.setDeleted(instanceJson.getBoolean(DELETED_KEY, false))
.setStatisticalCodeIds(toListOfStrings(instanceJson.getJsonArray(STATISTICAL_CODE_IDS_KEY)))
.setSourceRecordFormat(instanceJson.getString(SOURCE_RECORD_FORMAT_KEY))
.setStatusId(instanceJson.getString(STATUS_ID_KEY))
Expand Down Expand Up @@ -230,6 +233,7 @@ public JsonObject getJsonForStorage() {
json.put(PREVIOUSLY_HELD_KEY, previouslyHeld);
json.put(STAFF_SUPPRESS_KEY, staffSuppress);
json.put(DISCOVERY_SUPPRESS_KEY, discoverySuppress);
json.put(DELETED_KEY, deleted);
json.put(STATISTICAL_CODE_IDS_KEY, statisticalCodeIds);
if (sourceRecordFormat != null) json.put(SOURCE_RECORD_FORMAT_KEY, sourceRecordFormat);
json.put(STATUS_ID_KEY, statusId);
Expand Down Expand Up @@ -282,6 +286,7 @@ public JsonObject getJsonForResponse(WebContext context) {
putIfNotNull(json, PREVIOUSLY_HELD_KEY, getPreviouslyHeld());
putIfNotNull(json, STAFF_SUPPRESS_KEY, getStaffSuppress());
putIfNotNull(json, DISCOVERY_SUPPRESS_KEY, getDiscoverySuppress());
putIfNotNull(json, DELETED_KEY, getDeleted());
putIfNotNull(json, STATISTICAL_CODE_IDS_KEY, getStatisticalCodeIds());
putIfNotNull(json, SOURCE_RECORD_FORMAT_KEY, getSourceRecordFormat());
putIfNotNull(json, STATUS_ID_KEY, getStatusId());
Expand Down Expand Up @@ -516,6 +521,11 @@ public Instance setDiscoverySuppress(Boolean discoverySuppress) {
return this;
}

public Instance setDeleted(Boolean deleted) {
this.deleted = deleted;
return this;
}

public Instance setStatisticalCodeIds(List<String> statisticalCodeIds) {
this.statisticalCodeIds = statisticalCodeIds;
return this;
Expand Down Expand Up @@ -693,6 +703,10 @@ public Boolean getDiscoverySuppress() {
return discoverySuppress;
}

public Boolean getDeleted() {
return deleted;
}

public List<String> getStatisticalCodeIds() {
return statisticalCodeIds;
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/folio/inventory/resources/Instances.java
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,9 @@ private void softDelete(RoutingContext routingContext) {
private void updateVisibility(Instance instance, RoutingContext routingContext, InstanceCollection instanceCollection) {
instance.setDiscoverySuppress(true);
instance.setStaffSuppress(true);
instance.setDeleted(true);
instanceCollection.update(instance, v -> {
log.info("staffSuppress and discoverySuppress properties are set to true for instance {}",
log.info("staffSuppress, discoverySuppress and deleted properties are set to true for instance {}",
instance.getId());
noContent(routingContext.response());
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public static Instance mergeFieldsWhichAreNotControlled(Instance existing, org.f
.withVersion(asIntegerOrNull(existing.getVersion()))
.withDiscoverySuppress(existing.getDiscoverySuppress())
.withStaffSuppress(existing.getStaffSuppress())
.withDeleted(existing.getDeleted())
.withPreviouslyHeld(existing.getPreviouslyHeld())
.withCatalogedDate(existing.getCatalogedDate())
.withStatusId(existing.getStatusId())
Expand Down
1 change: 1 addition & 0 deletions src/test/java/api/InstancesApiExamples.java
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ public void canSoftDeleteInstance() {

assertTrue(getResponse.getJson().getBoolean("staffSuppress"));
assertTrue(getResponse.getJson().getBoolean("discoverySuppress"));
assertTrue(getResponse.getJson().getBoolean("deleted"));

Response getDeletedSourceRecordResponse = sourceRecordStorageClient.getById(instanceId);
assertEquals(getDeletedSourceRecordResponse.getStatusCode(), HttpStatus.HTTP_NOT_FOUND.toInt());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ public void shouldPopulateTargetInstanceWithNonMarcControlledFields(TestContext
Instance localSourceInstance = new Instance(instanceId, "1", "001", "MARC", "testTitle", UUID.randomUUID().toString())
.setDiscoverySuppress(Boolean.TRUE)
.setStaffSuppress(Boolean.TRUE)
.setDeleted(Boolean.TRUE)
.setCatalogedDate("1970-01-01")
.setStatusId(UUID.randomUUID().toString())
.setStatisticalCodeIds(List.of(UUID.randomUUID().toString()))
Expand Down Expand Up @@ -654,6 +655,7 @@ public void shouldPopulateTargetInstanceWithNonMarcControlledFields(TestContext
testContext.assertEquals(targetInstanceHrid, targetInstanceWithNonMarcData.getHrid());
testContext.assertEquals(localSourceInstance.getDiscoverySuppress(), targetInstanceWithNonMarcData.getDiscoverySuppress());
testContext.assertEquals(localSourceInstance.getStaffSuppress(), targetInstanceWithNonMarcData.getStaffSuppress());
testContext.assertEquals(localSourceInstance.getDeleted(), targetInstanceWithNonMarcData.getDeleted());
testContext.assertEquals(localSourceInstance.getCatalogedDate(), targetInstanceWithNonMarcData.getCatalogedDate());
testContext.assertEquals(localSourceInstance.getStatusId(), targetInstanceWithNonMarcData.getStatusId());
testContext.assertEquals(localSourceInstance.getStatisticalCodeIds(), targetInstanceWithNonMarcData.getStatisticalCodeIds());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.folio.inventory.storage.Storage;
import org.folio.inventory.support.http.client.OkapiHttpClient;
import org.folio.inventory.support.http.client.Response;
import org.folio.kafka.exception.DuplicateEventException;
import org.folio.processing.mapping.MappingManager;
import org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters;
import org.folio.processing.mapping.mapper.reader.Reader;
Expand All @@ -53,6 +54,7 @@
import org.folio.rest.jaxrs.model.ParsedRecord;
import org.folio.rest.jaxrs.model.ProfileSnapshotWrapper;
import org.folio.rest.jaxrs.model.Record;
import org.hamcrest.junit.internal.ThrowableCauseMatcher;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
Expand All @@ -79,6 +81,7 @@
import java.util.function.Consumer;

import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static java.lang.String.format;
import static java.util.concurrent.CompletableFuture.completedStage;
import static org.apache.http.HttpStatus.SC_CREATED;
import static org.folio.ActionProfile.FolioRecord.INSTANCE;
Expand All @@ -90,16 +93,18 @@
import static org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.PAYLOAD_USER_ID;
import static org.folio.inventory.dataimport.util.AdditionalFieldsUtil.TAG_005;
import static org.folio.inventory.dataimport.util.AdditionalFieldsUtil.dateTime005Formatter;
import static org.folio.inventory.dataimport.util.DataImportConstants.UNIQUE_ID_ERROR_MESSAGE;
import static org.folio.inventory.dataimport.util.DataImportConstants.ALREADY_EXISTS_ERROR_MSG;
import static org.folio.rest.jaxrs.model.ProfileType.ACTION_PROFILE;
import static org.folio.rest.jaxrs.model.ProfileType.JOB_PROFILE;
import static org.folio.rest.jaxrs.model.ProfileType.MAPPING_PROFILE;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
Expand Down Expand Up @@ -945,9 +950,8 @@ public void shouldNotProcessEventWhenRecordToInstanceFutureFails() throws Execut
future.get(5, TimeUnit.SECONDS);
}


@Test(expected = Exception.class)
public void shouldNotProcessEventEvenIfDuplicatedInventoryStorageErrorExists() throws InterruptedException, ExecutionException, TimeoutException {
@Test()
public void shouldNotProcessEventEvenIfDuplicatedInventoryStorageErrorExists() {
Reader fakeReader = Mockito.mock(Reader.class);

String instanceTypeId = "fe19bae4-da28-472b-be90-d442e2428ead";
Expand All @@ -965,7 +969,7 @@ public void shouldNotProcessEventEvenIfDuplicatedInventoryStorageErrorExists() t
when(instanceIdStorageService.store(any(), any(), any())).thenReturn(Future.succeededFuture(recordToInstance));
doAnswer(invocationOnMock -> {
Consumer<Failure> failureHandler = invocationOnMock.getArgument(2);
failureHandler.accept(new Failure(UNIQUE_ID_ERROR_MESSAGE, 400));
failureHandler.accept(new Failure(format(ALREADY_EXISTS_ERROR_MSG, instanceId), 400));
return null;
}).when(instanceRecordCollection).add(any(), any(), any());

Expand All @@ -989,7 +993,8 @@ public void shouldNotProcessEventEvenIfDuplicatedInventoryStorageErrorExists() t

CompletableFuture<DataImportEventPayload> future = createInstanceEventHandler.handle(dataImportEventPayload);

future.get(5, TimeUnit.SECONDS);
ExecutionException actualException = assertThrows(ExecutionException.class, () -> future.get(5, TimeUnit.SECONDS));
assertThat(actualException, ThrowableCauseMatcher.hasCause(instanceOf(DuplicateEventException.class)));
}

@Test(expected = Exception.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public void shouldMergeInstances() {
existing.setStatisticalCodeIds(statisticalCodeIds);
existing.setDiscoverySuppress(true);
existing.setStaffSuppress(true);
existing.setDeleted(true);
existing.setPreviouslyHeld(true);
existing.setCatalogedDate("");
existing.setStatusId("30773a27-b485-4dab-aeb6-b8c04fa3cb26");
Expand All @@ -85,6 +86,7 @@ public void shouldMergeInstances() {
assertEquals(statisticalCodeIds, instance.getStatisticalCodeIds());
assertTrue(instance.getDiscoverySuppress());
assertTrue(instance.getStaffSuppress());
assertTrue(instance.getDeleted());
assertTrue(instance.getPreviouslyHeld());
assertEquals("", instance.getCatalogedDate());
assertEquals("30773a27-b485-4dab-aeb6-b8c04fa3cb26", instance.getStatusId());
Expand Down
Loading

0 comments on commit e3dfeff

Please sign in to comment.