Skip to content

Commit

Permalink
Merge pull request #1402 from folio-org/CIRC-1999
Browse files Browse the repository at this point in the history
CIRC-1999 Use query based endpoint for fetchByBarcode
  • Loading branch information
MagzhanArtykov authored Dec 12, 2023
2 parents fd6a0b9 + a2059c1 commit 089d33e
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 90 deletions.
9 changes: 4 additions & 5 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -1692,7 +1692,7 @@
"circulation.rules.loan-policy.get",
"circulation.rules.request-policy.get",
"inventory-storage.items.item.put",
"circulation-item-storage.items.item.put",
"circulation-item.item.put",
"circulation.internal.fetch-items",
"users.item.get",
"users.collection.get",
Expand Down Expand Up @@ -1740,7 +1740,7 @@
"circulation.rules.loan-policy.get",
"circulation.rules.request-policy.get",
"inventory-storage.items.item.put",
"circulation-item-storage.items.item.put",
"circulation-item.item.put",
"circulation.internal.fetch-items",
"users.item.get",
"users.collection.get",
Expand Down Expand Up @@ -2327,9 +2327,8 @@
"description" : "Internal permission set for fetching item(s)",
"subPermissions": [
"inventory-storage.items.item.get",
"circulation-item-storage.item.collection.get",
"circulation-item-storage.items.collection.get",
"circulation-item-storage.items.item.get",
"circulation-item.collection.get",
"circulation-item.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 @@ -23,7 +23,6 @@
import java.lang.invoke.MethodHandles;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function;
Expand Down Expand Up @@ -64,7 +63,6 @@ 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 @@ -74,8 +72,7 @@ public ItemRepository(Clients clients) {
new MaterialTypeRepository(clients), new InstanceRepository(clients),
new HoldingsRepository(clients.holdingsStorage()),
new LoanTypeRepository(clients.loanTypesStorage()),
clients.circulationItemClient(),
clients.circulationItemsByIdsClient());
clients.circulationItemClient());
}

public CompletableFuture<Result<Item>> fetchFor(ItemRelatedRecord itemRelatedRecord) {
Expand Down Expand Up @@ -147,21 +144,13 @@ private CompletableFuture<Result<Item>> getAvailableItem(
}

public CompletableFuture<Result<Item>> fetchByBarcode(String barcode) {
return fetchItemByBarcode(barcode)
return fetchItemByBarcode(barcode, createItemFinder())
.thenComposeAsync(itemResult -> itemResult.after(when(item -> ofAsync(item::isNotFound),
item -> fetchCirculationItemByBarcode(barcode), item -> completedFuture(itemResult))))
item -> fetchItemByBarcode(barcode, createCirculationItemFinder())
, item -> completedFuture(itemResult))))
.thenComposeAsync(this::fetchItemRelatedRecords);
}

private CompletableFuture<Result<Item>> fetchCirculationItemByBarcode(String barcode) {
final var mapper = new ItemMapper();

return SingleRecordFetcher.jsonOrNull(circulationItemClient, "item")
.fetchWithQueryStringParameters(Map.of("barcode", barcode))
.thenApply(mapResult(identityMap::add))
.thenApply(r -> r.map(mapper::toDomain));
}

public CompletableFuture<Result<Item>> fetchById(String itemId) {
return fetchItem(itemId)
.thenComposeAsync(itemResult -> itemResult.after(when(item -> ofAsync(item::isNotFound),
Expand Down Expand Up @@ -292,10 +281,9 @@ public CompletableFuture<Result<JsonObject>> fetchItemAsJson(String itemId) {
.thenApply(mapResult(identityMap::add));
}

private CompletableFuture<Result<Item>> fetchItemByBarcode(String barcode) {
private CompletableFuture<Result<Item>> fetchItemByBarcode(String barcode, CqlQueryFinder<JsonObject> finder) {
log.info("Fetching item with barcode: {}", barcode);

final var finder = createItemFinder();
final var mapper = new ItemMapper();

return finder.findByQuery(exactMatch("barcode", barcode), one())
Expand Down Expand Up @@ -421,6 +409,6 @@ private CqlQueryFinder<JsonObject> createItemFinder() {
}

private CqlQueryFinder<JsonObject> createCirculationItemFinder() {
return new CqlQueryFinder<>(circulationItemsByIdsClient, "items", identity());
return new CqlQueryFinder<>(circulationItemClient, "items", identity());
}
}
12 changes: 0 additions & 12 deletions src/main/java/org/folio/circulation/support/Clients.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ 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 @@ -137,7 +136,6 @@ 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 @@ -376,10 +374,6 @@ public CollectionResourceClient circulationItemClient() {
return circulationItemClient;
}

public CollectionResourceClient circulationItemsByIdsClient() {
return circulationItemsByIdsClient;
}

private static CollectionResourceClient getCollectionResourceClient(
OkapiHttpClient client, WebContext context,
String path)
Expand Down Expand Up @@ -807,12 +801,6 @@ 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
19 changes: 19 additions & 0 deletions src/test/java/api/loans/CheckInByBarcodeTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,25 @@ void cannotCheckInWithoutACheckInDate() {
"Checkin request must have an check in date")));
}

@Test
void canCheckInAnDcbItem() {
final UUID checkInServicePointId = servicePointsFixture.cd1().getId();
IndividualResource instance = instancesFixture.basedUponDunkirk();
IndividualResource holdings = holdingsFixture.defaultWithHoldings(instance.getId());
IndividualResource locationsResource = locationsFixture.mainFloor();
var barcode = "100002222";
final IndividualResource circulationItem = circulationItemsFixture.createCirculationItem(barcode, holdings.getId(), locationsResource.getId());
final CheckInByBarcodeResponse checkInResponse = checkInFixture.checkInByBarcode(circulationItem, ZonedDateTime.now(), checkInServicePointId);

assertThat("Response should include an item",
checkInResponse.getJson().containsKey("item"), is(true));

final JsonObject itemFromResponse = checkInResponse.getItem();

assertThat("barcode is included for item",
itemFromResponse.getString("barcode"), is(barcode));
}

@Test
void canCheckInAnItemWithoutAnOpenLoan() {
final UUID checkInServicePointId = servicePointsFixture.cd1().getId();
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/api/loans/LoanAPITests.java
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ void loanInCollectionDoesProvideItemInformationForCirculationItem() {
IndividualResource holdings = holdingsFixture.defaultWithHoldings(instance.getId());

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

JsonObject loan = loansFixture.getLoans().getFirst();
Expand Down
133 changes: 121 additions & 12 deletions src/test/java/api/support/builders/CirculationItemsBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,133 @@

import java.util.UUID;

public class CirculationItemsBuilder implements Builder {
public class CirculationItemsBuilder extends JsonBuilder implements Builder {

private final JsonObject representation;
private final UUID itemId;
private final String barcode;
private final UUID holdingId;
private final UUID locationId;
private final UUID materialTypeId;
private final UUID loanTypeId;
private final boolean isDcb;
private final String lendingLibraryCode;

public CirculationItemsBuilder(UUID itemId, String barcode, UUID holdingId, UUID locationId, UUID materialTypeId, UUID loanTypeId, boolean isDcb) {
public CirculationItemsBuilder() {
this(UUID.randomUUID(),
"036000291452",
UUID.randomUUID(),
UUID.randomUUID(),
UUID.randomUUID(),
UUID.randomUUID(),
true,
"11223");
}

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

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);
this.itemId = itemId;
this.barcode = barcode;
this.holdingId = holdingId;
this.locationId = locationId;
this.materialTypeId = materialTypeId;
this.loanTypeId = loanTypeId;
this.isDcb = isDcb;
this.lendingLibraryCode = lendingLibraryCode;
}

@Override
public JsonObject create() {
JsonObject representation = new JsonObject();

representation.put("id", itemId);
representation.put("holdingsRecordId", holdingId);
representation.put("effectiveLocationId", locationId);
representation.put("barcode", barcode);
representation.put("materialTypeId", materialTypeId);
representation.put("temporaryLoanTypeId", loanTypeId);
representation.put("dcbItem", isDcb);
representation.put("lendingLibraryCode", lendingLibraryCode);

return representation;
}

public CirculationItemsBuilder withBarcode(String barcode) {
return new CirculationItemsBuilder(
this.itemId,
barcode,
this.holdingId,
this.locationId,
this.materialTypeId,
this.loanTypeId,
this.isDcb,
this.lendingLibraryCode);
}

public CirculationItemsBuilder withHoldingId(UUID holdingId) {
return new CirculationItemsBuilder(
this.itemId,
this.barcode,
holdingId,
this.locationId,
this.materialTypeId,
this.loanTypeId,
this.isDcb,
this.lendingLibraryCode);
}

public CirculationItemsBuilder withItemId(UUID itemId) {
return new CirculationItemsBuilder(
itemId,
this.barcode,
this.holdingId,
this.locationId,
this.materialTypeId,
this.loanTypeId,
this.isDcb,
this.lendingLibraryCode);
}

public CirculationItemsBuilder withLocationId(UUID locationId) {
return new CirculationItemsBuilder(
this.itemId,
this.barcode,
this.holdingId,
locationId,
this.materialTypeId,
this.loanTypeId,
this.isDcb,
this.lendingLibraryCode);
}

public CirculationItemsBuilder withLoanType(UUID loanTypeId) {
return new CirculationItemsBuilder(
this.itemId,
this.barcode,
this.holdingId,
this.locationId,
this.materialTypeId,
loanTypeId,
this.isDcb,
this.lendingLibraryCode);
}

public CirculationItemsBuilder withMaterialType(UUID materialTypeId) {
return new CirculationItemsBuilder(
this.itemId,
this.barcode,
this.holdingId,
this.locationId,
materialTypeId,
this.loanTypeId,
this.isDcb,
this.lendingLibraryCode);
}

}
6 changes: 0 additions & 6 deletions src/test/java/api/support/fakes/FakeOkapi.java
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,6 @@ 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")
Expand Down
11 changes: 5 additions & 6 deletions src/test/java/api/support/fixtures/CirculationItemsFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.UUID;

public class CirculationItemsFixture {
private final ResourceClient circulationItemsByIdsClient;
private final ResourceClient circulationItemClient;
private final MaterialTypesFixture materialTypesFixture;
private final LoanTypesFixture loanTypesFixture;
Expand All @@ -16,15 +15,15 @@ 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);
public IndividualResource createCirculationItem(String barcode, UUID holdingId, UUID locationId) {
CirculationItemsBuilder circulationItemsBuilder = new CirculationItemsBuilder().withBarcode(barcode).withHoldingId(holdingId)
.withLoanType(loanTypesFixture.canCirculate().getId()).withMaterialType(materialTypesFixture.book().getId())
.withLocationId(locationId);
return circulationItemClient.create(circulationItemsBuilder);
}
}
4 changes: 0 additions & 4 deletions src/test/java/api/support/http/InterfaceUrls.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ 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);
}
Expand Down
6 changes: 1 addition & 5 deletions src/test/java/api/support/http/ResourceClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,8 @@ 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");
return new ResourceClient(InterfaceUrls::circulationItemUrl, "items");
}

public static ResourceClient forHoldings() {
Expand Down
Loading

0 comments on commit 089d33e

Please sign in to comment.