Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import org.folio.inventoryupdate.entities.Instance;
import org.folio.inventoryupdate.entities.InventoryRecord;
import org.folio.inventoryupdate.entities.Item;
import org.folio.inventoryupdate.foreignconstraints.OrdersStorage;
import org.folio.inventoryupdate.remotereferences.OrdersStorage;
import org.folio.inventoryupdate.instructions.ProcessingInstructionsDeletion;
import org.folio.okapi.common.OkapiClient;

Expand Down Expand Up @@ -49,7 +49,7 @@ public Future<Void> planInventoryDelete(OkapiClient okapiClient, ProcessingInstr
}

public static Future<Void> setDeleteConstraintIfReferencedByAcquisitions(OkapiClient okapiClient, Instance existingInstance) {
return OrdersStorage.lookupPurchaseOrderLines(okapiClient, existingInstance.getUUID())
return new OrdersStorage().lookupPurchaseOrderLinesByInstanceId(okapiClient, existingInstance.getUUID())
.onComplete(poLinesLookup -> {
if (!poLinesLookup.result().isEmpty()) {
existingInstance.handleDeleteProtection(InventoryRecord.DeletionConstraint.PO_LINE_REFERENCE);
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/org/folio/inventoryupdate/PostProcessing.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.folio.inventoryupdate;

import io.vertx.core.Future;
import org.folio.inventoryupdate.entities.Repository;
import org.folio.inventoryupdate.remotereferences.OrderLinesPatching;
import org.folio.okapi.common.OkapiClient;

public class PostProcessing {

private PostProcessing() {
throw new IllegalStateException("SC");
}

public static Future<Void> process(OkapiClient okapiClient, Repository repository) {
return OrderLinesPatching.processPoLineReferences(okapiClient, repository);
}
}
2 changes: 2 additions & 0 deletions src/main/java/org/folio/inventoryupdate/UpdatePlan.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public Future<InventoryUpdateOutcome> upsertBatch(RoutingContext routingContext,
new JsonObject());

if (inventoryUpdated.succeeded()) {
PostProcessing.process(getOkapiClient(routingContext), repository);
response.put("metrics", getUpdateMetricsFromRepository().asJson());
promise.complete(
new InventoryUpdateOutcome(response)
Expand Down Expand Up @@ -425,6 +426,7 @@ public UpdateMetrics getUpdateMetricsFromRepository() {
existingSet.getItems()).flatMap(Collection::stream).collect(Collectors.toList());

for (InventoryRecord inventoryRecord : holdingsRecordsAndItemsInExistingSet) {
// Outcomes of deletes are registered on the existing records
if (inventoryRecord.isDeleting()) {
metrics.entity(inventoryRecord.entityType()).transaction(inventoryRecord.getTransaction()).outcomes.increment(inventoryRecord.getOutcome());
}
Expand Down
35 changes: 24 additions & 11 deletions src/main/java/org/folio/inventoryupdate/UpdatePlanAllHRIDs.java
Original file line number Diff line number Diff line change
Expand Up @@ -236,26 +236,27 @@ private void planInstanceHoldingsAndItems(PairedRecordSets pair) {
incomingInstance.setTransition(CREATE).generateUUIDIfNotProvided();
}
// Remaining holdings and item transactions: Creates, imports from other Instance(s)
// Find incoming holdings we didn't already resolve above
// Find incoming holdings we didn't already resolve (UPDATE or DELETE) above
List<HoldingsRecord> holdingsRecords =
incomingSet.getHoldingsRecordsByTransactionType(Transaction.UNKNOWN);
for (HoldingsRecord holdingsRecord : holdingsRecords) {
planToCreateNewHoldingsRecordOrMoveExistingOver(holdingsRecord, rules);
}
// Find incoming items we didn't already resolve (update or delete) above
// Find incoming items we didn't already resolve (UPDATE or DELETE) above
List<Item> items = incomingSet.getItemsByTransactionType(Transaction.UNKNOWN);
for (Item item : items) {
planToCreateNewItemOnMoveExistingOver(item, rules);
planToCreateNewItemOrMoveExistingOver(item, rules, incomingInstance.getUUID());
}
}
}

private void planToCreateNewItemOnMoveExistingOver(Item item, ProcessingInstructionsUpsert rules) {
private void planToCreateNewItemOrMoveExistingOver(Item item, ProcessingInstructionsUpsert rules, String instanceId) {
if (repository.existingItemsByHrid.containsKey(item.getHRID())) {
// Import from different Instance
Item existing = repository.existingItemsByHrid.get(item.getHRID());
item.setTransition(UPDATE);
item.applyOverlays(existing, rules.forItem());
item.isSwitchingToInstance(instanceId);
} else {
// The HRID does not exist in Inventory, create
item.setTransition(CREATE).generateUUIDIfNotProvided();
Expand All @@ -265,8 +266,8 @@ private void planToCreateNewItemOnMoveExistingOver(Item item, ProcessingInstruct
private void planToCreateNewHoldingsRecordOrMoveExistingOver(HoldingsRecord holdingsRecord, ProcessingInstructionsUpsert rules) {
if (repository.existingHoldingsRecordsByHrid.containsKey(holdingsRecord.getHRID())) {
// Import from different Instance
HoldingsRecord existing = repository.existingHoldingsRecordsByHrid.get(holdingsRecord.getHRID());
holdingsRecord.setTransition(UPDATE).applyOverlays(existing, rules.forHoldingsRecord());
HoldingsRecord existingHoldingsRecord = repository.existingHoldingsRecordsByHrid.get(holdingsRecord.getHRID());
holdingsRecord.setTransition(UPDATE).applyOverlays(existingHoldingsRecord, rules.forHoldingsRecord());
} else {
// The HRID does not exist in Inventory, create
holdingsRecord.setTransition(CREATE).generateUUIDIfNotProvided();
Expand All @@ -276,7 +277,6 @@ private void planToCreateNewHoldingsRecordOrMoveExistingOver(HoldingsRecord hold
private static void planToDeleteOrRetainHoldingsRecord(HoldingsRecord existingHoldingsRecord, ProcessingInstructionsUpsert rules) {
existingHoldingsRecord.setTransition(DELETE);
if (rules.forHoldingsRecord().retainOmittedRecord(existingHoldingsRecord)) {
logger.info("Retain omitted record");
existingHoldingsRecord.handleDeleteProtection(InventoryRecord.DeletionConstraint.HOLDINGS_RECORD_PATTERN_MATCH);
existingHoldingsRecord.skip();
}
Expand All @@ -288,15 +288,28 @@ private static void planToDeleteOrRetainItem(Item existingItem, ProcessingInstru
if (rules.forItem().retainOmittedRecord(existingItem)) {
existingItem.handleDeleteProtection(InventoryRecord.DeletionConstraint.ITEM_PATTERN_MATCH);
existingItem.skip();
existingHoldingsRecord.handleDeleteProtection(InventoryRecord.DeletionConstraint.ITEM_PATTERN_MATCH);
existingHoldingsRecord.skip();
if (existingHoldingsRecord.isDeleting()) {
existingHoldingsRecord.handleDeleteProtection(InventoryRecord.DeletionConstraint.ITEM_PATTERN_MATCH);
existingHoldingsRecord.skip();
}
}
// and unless item appears to be still circulating
if (existingItem.isCirculating()) {
existingItem.handleDeleteProtection(InventoryRecord.DeletionConstraint.ITEM_STATUS);
existingItem.skip();
existingHoldingsRecord.handleDeleteProtection(InventoryRecord.DeletionConstraint.ITEM_STATUS);
existingHoldingsRecord.skip();
if (existingHoldingsRecord.isDeleting()) {
existingHoldingsRecord.handleDeleteProtection(InventoryRecord.DeletionConstraint.ITEM_STATUS);
existingHoldingsRecord.skip();
}
}
// and unless item is linked to a purchase order line
if (existingItem.isInAcquisitions()) {
existingItem.handleDeleteProtection(InventoryRecord.DeletionConstraint.PO_LINE_REFERENCE);
existingItem.skip();
if (existingHoldingsRecord.isDeleting()) {
existingHoldingsRecord.handleDeleteProtection(InventoryRecord.DeletionConstraint.PO_LINE_REFERENCE);
existingHoldingsRecord.skip();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void setUUID (String uuid) {
setItemsHoldingsRecordId(uuid);
}

@Override
@Override
public String generateUUID () {
String uuid = super.generateUUID();
setItemsHoldingsRecordId(uuid);
Expand All @@ -55,7 +55,9 @@ public void setInstanceId (String uuid) {
}

public void addItem(Item item) {
logger.info("ID-NE: items " + items);
items.add(item);
logger.info("ID-NE added item to " + items);
if (hasUUID() && ! item.hasHoldingsRecordId()) {
item.setHoldingsRecordId(getUUID());
}
Expand Down
28 changes: 27 additions & 1 deletion src/main/java/org/folio/inventoryupdate/entities/Item.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public class Item extends InventoryRecord {

public static final String HOLDINGS_RECORD_ID = "holdingsRecordId";
public static final String PO_LINE_ID = "purchaseOrderLineIdentifier";
private static final List<String> statusesIndicatingCirculatingItem =
Arrays.asList("Awaiting delivery",
"Awaiting pickup",
Expand All @@ -19,6 +20,9 @@ public class Item extends InventoryRecord {
"Paged",
"In transit");

private boolean isTransitingToAnotherInstance = false;
private String newInstanceId;


public Item(JsonObject item, JsonObject originJson) {
this.jsonRecord = item;
Expand Down Expand Up @@ -80,4 +84,26 @@ public boolean isCirculating() {
return statusesIndicatingCirculatingItem.contains(getStatusName());
}

}
public boolean isInAcquisitions() {
return jsonRecord.getString(PO_LINE_ID) != null && !jsonRecord.getString(PO_LINE_ID).isEmpty();
}

public String getPurchaseOrderLineIdentifier() {
return jsonRecord.getString(PO_LINE_ID);
}

public boolean isSwitchingInstance() {
return isTransitingToAnotherInstance;
}

public void isSwitchingToInstance(String instanceId) {
newInstanceId = instanceId;
isTransitingToAnotherInstance = true;
}

public String getNewInstanceId () {
return newInstanceId;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.List;
import java.util.Map;


import static org.folio.inventoryupdate.entities.InventoryRecordSet.*;

public abstract class Repository {
Expand All @@ -31,7 +32,6 @@ public abstract class Repository {

public final Map<String,HoldingsRecord> existingHoldingsRecordsByHrid = new HashMap<>();


// List of incoming record sets paired with existing record sets
protected final List<PairedRecordSets> pairsOfRecordSets = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ protected void setExistingRecordSets () {
}
}


private Future<Void> requestInstanceSetsByHRIDs(RoutingContext routingContext,
List<String> hrids) {
OkapiClient okapiClient = InventoryStorage.getOkapiClient(routingContext);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.folio.inventoryupdate.remotereferences;

import io.vertx.core.Future;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.JsonObject;
import org.folio.inventoryupdate.entities.Item;
import org.folio.inventoryupdate.entities.Repository;
import org.folio.okapi.common.GenericCompositeFuture;
import org.folio.okapi.common.OkapiClient;

import java.util.ArrayList;
import java.util.List;


public class OrderLinesPatching {

private static final Logger logger = LoggerFactory.getLogger("inventory-update");

private OrderLinesPatching() {
throw new IllegalStateException("SC");
}

public static Future<Void> processPoLineReferences (OkapiClient okapiClient, Repository repository) {
List<Future<Void>> orderLinePatchingFutures = new ArrayList<>();
for (Item item : repository.getItemsToUpdate()) {
if (item.isSwitchingInstance() && item.getPurchaseOrderLineIdentifier() != null) {
logger.info("Switching PO line '" + item.getPurchaseOrderLineIdentifier() + "' to instance '" + item.getNewInstanceId() + "'");
JsonObject patchBody = new JsonObject()
.put("operation", "Replace Instance Ref")
.put("replaceInstanceRef",
new JsonObject()
.put("holdingsOperation", "Move")
.put("newInstanceId", item.getNewInstanceId()));
orderLinePatchingFutures.add(new Orders().patchOrderLine(okapiClient, item.getPurchaseOrderLineIdentifier(), patchBody));
}
}
return GenericCompositeFuture.join(orderLinePatchingFutures).mapEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.folio.inventoryupdate.remotereferences;

import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.JsonObject;
import org.folio.okapi.common.OkapiClient;

public class Orders {

private final OrdersConfiguration ordersConfiguration;
static class OrdersConfiguration {
public OrdersConfiguration() {
// SC
}
public String ordersPath() {
return "/orders/order-lines";
}
}
private static final Logger logger = LoggerFactory.getLogger("inventory-update");

public Orders() {
ordersConfiguration = new OrdersConfiguration();
}

public Future<Void> patchOrderLine(OkapiClient okapiClient, String purchaseOrderLineId, JsonObject patchBody) {
Promise<Void> promise = Promise.promise();
okapiClient.request(HttpMethod.PATCH, ordersConfiguration.ordersPath() + "/" + purchaseOrderLineId, patchBody.toString())
.onComplete(response -> {
if (response.failed()) {
logger.error("Problem patching order line: " + response.cause());
}
promise.complete();
});
return promise.future();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.folio.inventoryupdate.remotereferences;

import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import org.folio.okapi.common.OkapiClient;

public class OrdersStorage {

private final OrdersStorageConfiguration config;
static class OrdersStorageConfiguration {
public OrdersStorageConfiguration () {
// SC
}
public String ordersStoragePath() {
return "/orders-storage/po-lines";
}
public String purchaseOrderLines() {
return "poLines";
}
}

public OrdersStorage() {
config = new OrdersStorageConfiguration();
}

public Future<JsonArray> lookupPurchaseOrderLinesByInstanceId(OkapiClient okapiClient, String instanceId) {
Promise<JsonArray> promise = Promise.promise();
okapiClient.get(config.ordersStoragePath() + "?query=instanceId==" + instanceId)
.onComplete(response -> {
if (response.succeeded()) {
promise.complete(new JsonObject(response.result()).getJsonArray(config.purchaseOrderLines()));
} else {
promise.complete(new JsonArray());
}
});
return promise.future();
}
}
Loading