Skip to content

Commit

Permalink
[CIRC-1966]-Added integration with mod-circulation-item (#1379)
Browse files Browse the repository at this point in the history
* [CIRC-1966]-Added intigration with mod-circulation-item

* [CIRC-1966]-Added intigration with mod-circulation-item

* [CIRC-1966]-Added intigration with mod-circulation-item

* [CIRC-1966]-Added intigration with mod-circulation-item
  • Loading branch information
SinghAdes authored Nov 23, 2023
1 parent 86a5a85 commit 4bad050
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 19 deletions.
3 changes: 2 additions & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -2326,8 +2326,9 @@
"description" : "Internal permission set for fetching item(s)",
"subPermissions": [
"inventory-storage.items.item.get",
"circulation-item-storage.items.item.get",
"circulation-item-storage.item.collection.get",
"circulation-item-storage.items.collection.get",
"circulation-item-storage.items.item.get",
"inventory-storage.items.collection.get",
"inventory-storage.holdings.item.get",
"inventory-storage.holdings.collection.get",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class ItemRepository {
private final HoldingsRepository holdingsRepository;
private final LoanTypeRepository loanTypeRepository;
private final CollectionResourceClient circulationItemClient;
private final CollectionResourceClient circulationItemsByIdsClient;
private final IdentityMap identityMap = new IdentityMap(
item -> getProperty(item, "id"));

Expand All @@ -72,7 +73,9 @@ public ItemRepository(Clients clients) {
new ServicePointRepository(clients)),
new MaterialTypeRepository(clients), new InstanceRepository(clients),
new HoldingsRepository(clients.holdingsStorage()),
new LoanTypeRepository(clients.loanTypesStorage()), clients.circulationItemClient());
new LoanTypeRepository(clients.loanTypesStorage()),
clients.circulationItemClient(),
clients.circulationItemsByIdsClient());
}

public CompletableFuture<Result<Item>> fetchFor(ItemRelatedRecord itemRelatedRecord) {
Expand Down Expand Up @@ -254,6 +257,23 @@ private CompletableFuture<Result<MultipleRecords<Item>>> fetchItems(Collection<S
final var mapper = new ItemMapper();

return finder.findByIds(itemIds)
.thenApply(mapResult(identityMap::add))
.thenApply(mapResult(records -> records.mapRecords(mapper::toDomain)))
.thenCompose(res -> res.value().getTotalRecords() == itemIds.size()
? CompletableFuture.completedFuture(res)
: res.combineAfter(x -> lookupDcbItem(res, itemIds), MultipleRecords::combine));
}

private CompletableFuture<Result<MultipleRecords<Item>>>
lookupDcbItem(Result<MultipleRecords<Item>> inventoryItems, Collection<String> itemIds) {
log.debug("lookupDcbItem:: Looking up for DCB items");

var inventoryItemIds = inventoryItems.value().toKeys(Item::getItemId);
final var finder = new CqlIndexValuesFinder<>(createCirculationItemFinder());
var dcbItemIds = itemIds.stream().filter(ids -> !inventoryItemIds.contains(ids)).toList();
final var mapper = new ItemMapper();

return finder.findByIds(dcbItemIds)
.thenApply(mapResult(identityMap::add))
.thenApply(mapResult(records -> records.mapRecords(mapper::toDomain)));
}
Expand Down Expand Up @@ -398,4 +418,8 @@ public CompletableFuture<Result<MultipleRecords<Item>>> fetchItemsRelatedRecords
private CqlQueryFinder<JsonObject> createItemFinder() {
return new CqlQueryFinder<>(itemsClient, "items", identity());
}

private CqlQueryFinder<JsonObject> createCirculationItemFinder() {
return new CqlQueryFinder<>(circulationItemsByIdsClient, "items", identity());
}
}
12 changes: 12 additions & 0 deletions src/main/java/org/folio/circulation/support/Clients.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public class Clients {
private final CollectionResourceClient departmentClient;
private final CollectionResourceClient checkOutLockStorageClient;
private final CollectionResourceClient circulationItemClient;
private final CollectionResourceClient circulationItemsByIdsClient;
private final GetManyRecordsClient settingsStorageClient;

public static Clients create(WebContext context, HttpClient httpClient) {
Expand Down Expand Up @@ -136,6 +137,7 @@ private Clients(OkapiHttpClient client, WebContext context) {
checkOutLockStorageClient = createCheckoutLockClient(client, context);
settingsStorageClient = createSettingsStorageClient(client, context);
circulationItemClient = createCirculationItemClient(client, context);
circulationItemsByIdsClient = createCirculationItemsByIdsClient(client, context);
}
catch(MalformedURLException e) {
throw new InvalidOkapiLocationException(context.getOkapiLocation(), e);
Expand Down Expand Up @@ -374,6 +376,10 @@ public CollectionResourceClient circulationItemClient() {
return circulationItemClient;
}

public CollectionResourceClient circulationItemsByIdsClient() {
return circulationItemsByIdsClient;
}

private static CollectionResourceClient getCollectionResourceClient(
OkapiHttpClient client, WebContext context,
String path)
Expand Down Expand Up @@ -801,6 +807,12 @@ private CollectionResourceClient createCirculationItemClient(
return getCollectionResourceClient(client, context, "/circulation-item");
}

private CollectionResourceClient createCirculationItemsByIdsClient(
OkapiHttpClient client, WebContext context) throws MalformedURLException {

return getCollectionResourceClient(client, context, "/circulation-item/items");
}

private GetManyRecordsClient createSettingsStorageClient(
OkapiHttpClient client, WebContext context)
throws MalformedURLException {
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/api/loans/LoanAPITests.java
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,21 @@ void loanInCollectionDoesNotProvideItemInformationForUnknownItem() {
loan.containsKey("item"), is(false));
}

@Test
void loanInCollectionDoesProvideItemInformationForCirculationItem() {
IndividualResource instance = instancesFixture.basedUponDunkirk();
IndividualResource holdings = holdingsFixture.defaultWithHoldings(instance.getId());

IndividualResource locationsResource = locationsFixture.mainFloor();
final IndividualResource circulationItem = circulationItemsFixture.createCirculationItem(UUID.randomUUID(), "100002222", holdings.getId(), locationsResource.getId());
loansFixture.createLoan(circulationItem, usersFixture.jessica());

JsonObject loan = loansFixture.getLoans().getFirst();

assertThat("should be item information available",
loan.containsKey("item"), is(true));
}

@Test
void canPageLoans() {
val user = usersFixture.steve();
Expand Down
24 changes: 14 additions & 10 deletions src/test/java/api/support/APITests.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.utility.DockerImageName;

import api.support.fakes.FakeModNotify;
import api.support.fakes.FakePubSub;
import api.support.fakes.FakeStorageModule;
import api.support.fixtures.AddInfoFixture;
import api.support.fixtures.AddressTypesFixture;
import api.support.fixtures.AgeToLostFixture;
Expand All @@ -43,6 +33,7 @@
import api.support.fixtures.CheckInFixture;
import api.support.fixtures.CheckOutFixture;
import api.support.fixtures.CheckOutLockFixture;
import api.support.fixtures.CirculationItemsFixture;
import api.support.fixtures.CirculationRulesFixture;
import api.support.fixtures.ClaimItemReturnedFixture;
import api.support.fixtures.ConfigurationsFixture;
Expand Down Expand Up @@ -79,6 +70,16 @@
import api.support.fixtures.TenantActivationFixture;
import api.support.fixtures.UserManualBlocksFixture;
import api.support.fixtures.UsersFixture;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.utility.DockerImageName;

import api.support.fakes.FakeModNotify;
import api.support.fakes.FakePubSub;
import api.support.fakes.FakeStorageModule;
import api.support.fixtures.policies.PoliciesActivationFixture;
import api.support.http.IndividualResource;
import api.support.http.ResourceClient;
Expand Down Expand Up @@ -239,6 +240,9 @@ public abstract class APITests {
protected final ProxyRelationshipsFixture proxyRelationshipsFixture
= new ProxyRelationshipsFixture(proxyRelationshipsClient);

protected final CirculationItemsFixture circulationItemsFixture = new CirculationItemsFixture(
materialTypesFixture, loanTypesFixture);

protected final UsersFixture usersFixture = new UsersFixture(usersClient,
patronGroupsFixture);

Expand Down
27 changes: 27 additions & 0 deletions src/test/java/api/support/builders/CirculationItemsBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package api.support.builders;

import io.vertx.core.json.JsonObject;

import java.util.UUID;

public class CirculationItemsBuilder implements Builder {

private final JsonObject representation;

public CirculationItemsBuilder(UUID itemId, String barcode, UUID holdingId, UUID locationId, UUID materialTypeId, UUID loanTypeId, boolean isDcb) {

this.representation = new JsonObject()
.put("id", itemId)
.put("holdingsRecordId", holdingId)
.put("effectiveLocationId", locationId)
.put("barcode", barcode)
.put("materialTypeId", materialTypeId)
.put("temporaryLoanTypeId", loanTypeId)
.put("dcbItem", isDcb);
}

@Override
public JsonObject create() {
return representation;
}
}
12 changes: 12 additions & 0 deletions src/test/java/api/support/fakes/FakeOkapi.java
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,18 @@ public void start(Promise<Void> startFuture) throws IOException {
.withRecordConstraint(this::userHasAlreadyAcquiredLock)
.create().register(router);

new FakeStorageModuleBuilder()
.withRootPath("/circulation-item/items")
.withCollectionPropertyName("items")
.withChangeMetadata()
.create().register(router);

new FakeStorageModuleBuilder()
.withRootPath("/circulation-item")
.withCollectionPropertyName("items")
.withChangeMetadata()
.create().register(router);

new FakeFeeFineOperationsModule().register(router);

server.requestHandler(router)
Expand Down
30 changes: 30 additions & 0 deletions src/test/java/api/support/fixtures/CirculationItemsFixture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package api.support.fixtures;

import api.support.builders.CirculationItemsBuilder;
import api.support.http.IndividualResource;
import api.support.http.ResourceClient;

import java.util.UUID;

public class CirculationItemsFixture {
private final ResourceClient circulationItemsByIdsClient;
private final ResourceClient circulationItemClient;
private final MaterialTypesFixture materialTypesFixture;
private final LoanTypesFixture loanTypesFixture;

public CirculationItemsFixture(
MaterialTypesFixture materialTypesFixture,
LoanTypesFixture loanTypesFixture) {

circulationItemsByIdsClient = ResourceClient.forCirculationItemsByIds();
circulationItemClient = ResourceClient.forCirculationItem();
this.materialTypesFixture = materialTypesFixture;
this.loanTypesFixture = loanTypesFixture;
}

public IndividualResource createCirculationItem(UUID itemId, String barcode, UUID holdingId, UUID locationId) {
CirculationItemsBuilder circulationItemsBuilder = new CirculationItemsBuilder(itemId, barcode, holdingId, locationId, materialTypesFixture.book().getId(), loanTypesFixture.canCirculate().getId(), true);
circulationItemClient.create(circulationItemsBuilder);
return circulationItemsByIdsClient.create(circulationItemsBuilder);
}
}
8 changes: 8 additions & 0 deletions src/test/java/api/support/http/InterfaceUrls.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ public static URL itemsStorageUrl(String subPath) {
return APITestContext.viaOkapiModuleUrl("/item-storage/items" + subPath);
}

public static URL circulationItemsByIdsUrl(String subPath) {
return APITestContext.viaOkapiModuleUrl("/circulation-item/items" + subPath);
}

public static URL circulationItemUrl(String subPath) {
return APITestContext.viaOkapiModuleUrl("/circulation-item" + subPath);
}

public static URL holdingsStorageUrl(String subPath) {
return APITestContext.viaOkapiModuleUrl("/holdings-storage/holdings" + subPath);
}
Expand Down
8 changes: 8 additions & 0 deletions src/test/java/api/support/http/ResourceClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ public static ResourceClient forItems() {
return new ResourceClient(InterfaceUrls::itemsStorageUrl, "items");
}

public static ResourceClient forCirculationItemsByIds() {
return new ResourceClient(InterfaceUrls::circulationItemsByIdsUrl, "items");
}

public static ResourceClient forCirculationItem() {
return new ResourceClient(InterfaceUrls::circulationItemUrl, "item");
}

public static ResourceClient forHoldings() {
return new ResourceClient(InterfaceUrls::holdingsStorageUrl, "holdingsRecords");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ItemRepositoryTests {
@Test
void canUpdateAnItemThatHasBeenFetched() {
final var itemsClient = mock(CollectionResourceClient.class);
final var repository = createRepository(itemsClient, null);
final var repository = createRepository(itemsClient, null, null);

final var itemId = UUID.randomUUID().toString();

Expand All @@ -63,7 +63,7 @@ void canUpdateAnItemThatHasBeenFetched() {

@Test
void cannotUpdateAnItemThatHasNotBeenFetched() {
final var repository = createRepository(null, null);
final var repository = createRepository(null, null, null);

final var notFetchedItem = dummyItem();

Expand All @@ -75,7 +75,7 @@ void cannotUpdateAnItemThatHasNotBeenFetched() {

@Test
void nullItemIsNotUpdated() {
final var repository = createRepository(null, null);
final var repository = createRepository(null, null, null);

final var updateResult = get(repository.updateItem(null));

Expand All @@ -87,8 +87,9 @@ void nullItemIsNotUpdated() {
void returnCirculationItemWhenNotFound() {
final var itemsClient = mock(CollectionResourceClient.class);
final var circulationItemsClient = mock(CollectionResourceClient.class);
final var repository = createRepository(itemsClient, circulationItemsClient);
final var itemId = UUID.randomUUID().toString();
final var circulationItemsByIdsClient = mock(CollectionResourceClient.class);
final var repository = createRepository(itemsClient, circulationItemsClient, circulationItemsByIdsClient);

final var circulationItemJson = new JsonObject()
.put("id", itemId)
Expand All @@ -109,8 +110,9 @@ void returnCirculationItemWhenNotFound() {
void canUpdateCirculationItemThatHasBeenFetched(){
final var itemsClient = mock(CollectionResourceClient.class);
final var circulationItemsClient = mock(CollectionResourceClient.class);
final var repository = createRepository(itemsClient, circulationItemsClient);
final var itemId = UUID.randomUUID().toString();
final var circulationItemsByIdsClient = mock(CollectionResourceClient.class);
final var repository = createRepository(itemsClient, circulationItemsClient, circulationItemsByIdsClient);

final var circulationItemJson = new JsonObject()
.put("id", itemId)
Expand All @@ -137,13 +139,14 @@ private void mockedClientGet(CollectionResourceClient client, String body) {
() -> new Response(200, body, "application/json")));
}

private ItemRepository createRepository(CollectionResourceClient itemsClient, CollectionResourceClient circulationItemClient) {
private ItemRepository createRepository(CollectionResourceClient itemsClient, CollectionResourceClient circulationItemClient, CollectionResourceClient circulationItemsByIdsClient) {
final var locationRepository = mock(LocationRepository.class);
final var materialTypeRepository = mock(MaterialTypeRepository.class);
final var instanceRepository = mock(InstanceRepository.class);
final var holdingsRepository = mock(HoldingsRepository.class);
final var loanTypeRepository = mock(LoanTypeRepository.class);


when(locationRepository.getEffectiveLocation(any()))
.thenReturn(ofAsync(Location::unknown));

Expand All @@ -158,7 +161,7 @@ private ItemRepository createRepository(CollectionResourceClient itemsClient, Co

return new ItemRepository(itemsClient, locationRepository,
materialTypeRepository, instanceRepository,
holdingsRepository, loanTypeRepository, circulationItemClient);
holdingsRepository, loanTypeRepository, circulationItemClient, circulationItemsByIdsClient);
}

private Item dummyItem() {
Expand Down

0 comments on commit 4bad050

Please sign in to comment.