Skip to content

Commit

Permalink
[MODORDERS-929] - Local shadow instance creation for linked instances (
Browse files Browse the repository at this point in the history
  • Loading branch information
Abdulkhakimov authored Sep 27, 2023
1 parent 7650d82 commit d2cfce1
Show file tree
Hide file tree
Showing 19 changed files with 452 additions and 32 deletions.
44 changes: 37 additions & 7 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,12 @@
"configuration.entries.collection.get",
"acquisitions-units-storage.units.collection.get",
"acquisitions-units-storage.memberships.collection.get",
"inventory.instances.item.get",
"inventory-storage.identifier-types.collection.get",
"isbn-utils.convert-to-13.get",
"finance-storage.budget-expense-classes.collection.get"
"finance-storage.budget-expense-classes.collection.get",
"user-tenants.collection.get",
"consortia.sharing-instances.item.post"
]
},
{
Expand Down Expand Up @@ -235,6 +238,7 @@
"finance-storage.budget-expense-classes.collection.get",
"inventory.instances.collection.get",
"inventory.instances.item.post",
"inventory.instances.item.get",
"inventory-storage.holdings.item.post",
"inventory-storage.holdings.collection.get",
"inventory-storage.items.collection.get",
Expand All @@ -257,7 +261,9 @@
"organizations-storage.organizations.collection.get",
"invoice.invoice-lines.collection.get",
"invoice.invoice-lines.item.put",
"orders-storage.order-invoice-relationships.collection.get"
"orders-storage.order-invoice-relationships.collection.get",
"user-tenants.collection.get",
"consortia.sharing-instances.item.post"
]
},
{
Expand Down Expand Up @@ -309,7 +315,9 @@
"orders-storage.po-lines.item.patch",
"orders-storage.po-lines.item.get",
"orders-storage.po-lines.item.put",
"orders-storage.pieces.collection.get"
"orders-storage.pieces.collection.get",
"user-tenants.collection.get",
"consortia.sharing-instances.item.post"
]
},
{
Expand Down Expand Up @@ -465,6 +473,7 @@
"inventory.items.item.put",
"inventory.items.collection.get",
"inventory-storage.holdings-sources.collection.get",
"inventory.instances.item.get",
"inventory.instances.item.post",
"inventory-storage.holdings.collection.get",
"inventory-storage.holdings.item.post",
Expand All @@ -487,7 +496,9 @@
"orders-storage.titles.item.get",
"orders-storage.titles.item.put",
"orders-storage.alerts.item.get",
"orders-storage.reporting-codes.item.get"
"orders-storage.reporting-codes.item.get",
"user-tenants.collection.get",
"consortia.sharing-instances.item.post"
]
},
{
Expand All @@ -506,6 +517,7 @@
"acquisitions-units-storage.units.collection.get",
"acquisitions-units-storage.memberships.collection.get",
"configuration.entries.collection.get",
"inventory.instances.item.get",
"inventory.instances.item.post",
"inventory.items.item.get",
"inventory.items.item.put",
Expand Down Expand Up @@ -536,7 +548,9 @@
"orders-storage.titles.item.get",
"orders-storage.titles.item.put",
"orders-storage.alerts.item.get",
"orders-storage.reporting-codes.item.get"
"orders-storage.reporting-codes.item.get",
"user-tenants.collection.get",
"consortia.sharing-instances.item.post"
]
},
{
Expand Down Expand Up @@ -748,7 +762,10 @@
"modulePermissions": [
"orders-storage.titles.collection.get",
"orders-storage.titles.item.post",
"orders-storage.po-lines.item.get"
"orders-storage.po-lines.item.get",
"inventory.instances.item.get",
"user-tenants.collection.get",
"consortia.sharing-instances.item.post"
]
},
{
Expand All @@ -761,7 +778,12 @@
"methods": ["PUT"],
"pathPattern": "/orders/titles/{id}",
"permissionsRequired": ["orders.titles.item.put"],
"modulePermissions": ["orders-storage.titles.item.put"]
"modulePermissions": [
"orders-storage.titles.item.put",
"inventory.instances.item.get",
"user-tenants.collection.get",
"consortia.sharing-instances.item.post"
]
},
{
"methods": ["DELETE"],
Expand Down Expand Up @@ -1132,12 +1154,20 @@
{
"id": "orders-storage.export-history",
"version": "1.0"
},
{
"id": "user-tenants",
"version": "1.0"
}
],
"optional": [
{
"id": "invoice",
"version": "7.0"
},
{
"id": "consortia",
"version": "1.0"
}
],
"permissionSets": [
Expand Down
5 changes: 0 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,6 @@
<version>1.4.2</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.folio</groupId>
<artifactId>folio-kafka-wrapper</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.folio</groupId>
<artifactId>data-import-processing-core</artifactId>
Expand Down
26 changes: 20 additions & 6 deletions src/main/java/org/folio/config/ApplicationConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import org.folio.service.caches.ConfigurationEntriesCache;
import org.folio.service.caches.InventoryCache;
import org.folio.service.configuration.ConfigurationEntriesService;
import org.folio.service.consortium.ConsortiumConfigurationService;
import org.folio.service.consortium.SharingInstanceService;
import org.folio.service.exchange.ExchangeRateProviderResolver;
import org.folio.service.exchange.FinanceExchangeRateService;
import org.folio.service.finance.FiscalYearService;
Expand Down Expand Up @@ -451,8 +453,8 @@ CompositeOrderDynamicDataPopulateService combinedPopulateService(CompositeOrderR

@Bean
TitlesService titlesService(RestClient restClient, PurchaseOrderLineService purchaseOrderLineService,
AcquisitionsUnitsService acquisitionsUnitsService) {
return new TitlesService(restClient, purchaseOrderLineService, acquisitionsUnitsService);
AcquisitionsUnitsService acquisitionsUnitsService, InventoryManager inventoryManager) {
return new TitlesService(restClient, purchaseOrderLineService, acquisitionsUnitsService, inventoryManager);
}

@Bean
Expand All @@ -477,8 +479,9 @@ ProtectionService protectionHelper(AcquisitionsUnitsService acquisitionsUnitsSer

@Bean
InventoryManager inventoryManager(RestClient restClient, ConfigurationEntriesCache configurationEntriesCache,
PieceStorageService pieceStorageService, InventoryCache inventoryCache, InventoryService inventoryService) {
return new InventoryManager(restClient, configurationEntriesCache, pieceStorageService, inventoryCache, inventoryService);
PieceStorageService pieceStorageService, InventoryCache inventoryCache, InventoryService inventoryService,
ConsortiumConfigurationService consortiumConfigurationService, SharingInstanceService sharingInstanceService) {
return new InventoryManager(restClient, configurationEntriesCache, pieceStorageService, inventoryCache, inventoryService, sharingInstanceService, consortiumConfigurationService);
}

@Bean
Expand Down Expand Up @@ -682,8 +685,9 @@ PurchaseOrderHelper purchaseOrderHelper(PurchaseOrderLineHelper purchaseOrderLin
RestClient restClient,
OrderLinePatchOperationHandlerResolver orderLinePatchOperationHandlerResolver,
PurchaseOrderLineService purchaseOrderLineService,
InventoryCache inventoryCache) {
return new OrderLinePatchOperationService(restClient, orderLinePatchOperationHandlerResolver, purchaseOrderLineService, inventoryCache);
InventoryCache inventoryCache,
InventoryManager inventoryManager) {
return new OrderLinePatchOperationService(restClient, orderLinePatchOperationHandlerResolver, purchaseOrderLineService, inventoryCache, inventoryManager);
}

@Bean PatchOperationHandler orderLineUpdateInstanceHandler(
Expand Down Expand Up @@ -733,4 +737,14 @@ OrderTemplatesService orderTemplatesService() {
@Bean POLInvoiceLineRelationService polInvoiceLineRelationService(InvoiceLineService invoiceLineService, PendingPaymentService pendingPaymentService, InvoiceTransactionSummariesService invoiceTransactionSummariesService, PoLineInvoiceLineHolderBuilder poLineInvoiceLineHolderBuilder) {
return new POLInvoiceLineRelationService(invoiceLineService, pendingPaymentService, invoiceTransactionSummariesService, poLineInvoiceLineHolderBuilder);
}

@Bean
ConsortiumConfigurationService consortiumConfigurationService(RestClient restClient) {
return new ConsortiumConfigurationService(restClient);
}

@Bean
SharingInstanceService sharingInstanceService(RestClient restClient) {
return new SharingInstanceService(restClient);
}
}
11 changes: 10 additions & 1 deletion src/main/java/org/folio/helper/PurchaseOrderLineHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ public Future<CompositePoLine> createPoLine(CompositePoLine compPOL, JsonObject
// The PO Line can be created only for order in Pending state
.map(this::validateOrderState)
.compose(po -> protectionService.isOperationRestricted(po.getAcqUnitIds(), ProtectedOperationType.CREATE, requestContext)
.compose(v -> createShadowInstanceIfNeeded(compPOL, requestContext))
.compose(v -> createPoLine(compPOL, po, requestContext)));
} else {
Errors errors = new Errors().withErrors(validationErrors).withTotalRecords(validationErrors.size());
Expand Down Expand Up @@ -297,6 +298,7 @@ public Future<Void> updateOrderLine(CompositePoLine compOrderLine, RequestContex
compOrderLine.setPoLineNumber(lineFromStorage.getString(PO_LINE_NUMBER));

return polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext)
.compose(v -> createShadowInstanceIfNeeded(compOrderLine, requestContext))
.compose(v -> updateOrderLine(compOrderLine, lineFromStorage, requestContext))
.compose(v -> updateEncumbranceStatus(compOrderLine, lineFromStorage, requestContext))
.compose(v -> polInvoiceLineRelationService.updateInvoiceLineReference(poLineInvoiceLineHolder, requestContext))
Expand Down Expand Up @@ -884,6 +886,13 @@ private Future<Void> verifyDeleteAllowed(PoLine line, RequestContext requestCont
.compose(order -> protectionService.isOperationRestricted(order.getAcqUnitIds(), DELETE, requestContext)));
}


private Future<Void> createShadowInstanceIfNeeded(CompositePoLine compositePoLine, RequestContext requestContext) {
String instanceId = compositePoLine.getInstanceId();
if (Boolean.TRUE.equals(compositePoLine.getIsPackage()) || Objects.isNull(instanceId)) {
return Future.succeededFuture();
}
return inventoryManager.createShadowInstanceIfNeeded(instanceId, requestContext)
.mapEmpty();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.folio.models.consortium;

public record ConsortiumConfiguration(String centralTenantId, String consortiumId) {
}
18 changes: 18 additions & 0 deletions src/main/java/org/folio/models/consortium/SharingInstance.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.folio.models.consortium;


import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.util.UUID;

@JsonIgnoreProperties(ignoreUnknown = true)
public record SharingInstance(UUID id,
UUID instanceIdentifier,
String sourceTenantId,
String targetTenantId,
SharingStatus status,
String error) {
public SharingInstance(UUID instanceIdentifier, String sourceTenantId, String targetTenantId) {
this(null, instanceIdentifier, sourceTenantId, targetTenantId, null, null);
}
}
38 changes: 38 additions & 0 deletions src/main/java/org/folio/models/consortium/SharingStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.folio.models.consortium;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

public enum SharingStatus {
COMPLETE("COMPLETE"),

ERROR("ERROR"),

IN_PROGRESS("IN_PROGRESS");

private final String value;

SharingStatus(String value) {
this.value = value;
}

@JsonValue
public String getValue() {
return value;
}

@Override
public String toString() {
return String.valueOf(value);
}

@JsonCreator
public static SharingStatus fromValue(String value) {
for (SharingStatus b : SharingStatus.values()) {
if (b.value.equals(value)) {
return b;
}
}
throw new IllegalArgumentException("Unexpected value '" + value + "'");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ private ResourcePathResolver() {
public static final String PREFIXES = "configuration.prefixes";
public static final String SUFFIXES = "configuration.suffixes";
public static final String TRANSACTIONS_ENDPOINT = "finance.transactions";
public static final String USER_TENANTS_ENDPOINT = "user.tenants";
public static final String FINANCE_RELEASE_ENCUMBRANCE = "finance.release-encumbrance";
public static final String BUDGET_EXPENSE_CLASSES = "finance-storage.budget-expense-classes";
public static final String CURRENT_BUDGET = "finance.current-budgets";
Expand Down Expand Up @@ -77,6 +78,7 @@ private ResourcePathResolver() {
apis.put(PREFIXES, "/orders-storage/configuration/prefixes");
apis.put(SUFFIXES, "/orders-storage/configuration/suffixes");
apis.put(TRANSACTIONS_ENDPOINT, "/finance/transactions");
apis.put(USER_TENANTS_ENDPOINT, "/user-tenants");
apis.put(FINANCE_RELEASE_ENCUMBRANCE, "/finance/release-encumbrance");
apis.put(BUDGET_EXPENSE_CLASSES, "/finance-storage/budget-expense-classes");
apis.put(CURRENT_BUDGET, "/finance/funds/%s/budget");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.folio.rest.core.exceptions;

/**
* Exception that used for consortium process
*/
public class ConsortiumException extends RuntimeException {
public ConsortiumException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.folio.service.consortium;

import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.folio.models.consortium.ConsortiumConfiguration;
import org.folio.rest.core.RestClient;
import org.folio.rest.core.models.RequestContext;
import org.folio.rest.core.models.RequestEntry;
import org.folio.rest.tools.utils.TenantTool;
import org.springframework.beans.factory.annotation.Value;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class ConsortiumConfigurationService {
private static final Logger logger = LogManager.getLogger(ConsortiumConfigurationService.class);

private static final String CONSORTIUM_ID_FIELD = "consortiumId";
private static final String CENTRAL_TENANT_ID_FIELD = "centralTenantId";
private static final String USER_TENANTS_ARRAY_IDENTIFIER = "userTenants";
private static final String USER_TENANTS_ENDPOINT = "/user-tenants";

@Value("${orders.cache.consortium-data.expiration.time.seconds:300}")
private long cacheExpirationTime;

private final RestClient restClient;
private final AsyncCache<String, Optional<ConsortiumConfiguration>> asyncCache;

public ConsortiumConfigurationService(RestClient restClient) {
this.restClient = restClient;

asyncCache = Caffeine.newBuilder()
.expireAfterWrite(cacheExpirationTime, TimeUnit.SECONDS)
.executor(task -> Vertx.currentContext().runOnContext(v -> task.run()))
.buildAsync();
}

public Future<Optional<ConsortiumConfiguration>> getConsortiumConfiguration(RequestContext requestContext) {
try {
var cacheKey = TenantTool.tenantId(requestContext.getHeaders());
return Future.fromCompletionStage(asyncCache.get(cacheKey, (key, executor) ->
getConsortiumConfigurationFromRemote(requestContext)));
} catch (Exception e) {
logger.error("Error when retrieving consortium configuration", e);
return Future.failedFuture(e);
}
}

private CompletableFuture<Optional<ConsortiumConfiguration>> getConsortiumConfigurationFromRemote(RequestContext requestContext) {
RequestEntry requestEntry = new RequestEntry(USER_TENANTS_ENDPOINT).withLimit(1);
return restClient.getAsJsonObject(requestEntry, requestContext)
.map(jsonObject -> jsonObject.getJsonArray(USER_TENANTS_ARRAY_IDENTIFIER))
.map(userTenants -> {
if (userTenants.isEmpty()) {
logger.debug("Central tenant and consortium id not found");
return Optional.<ConsortiumConfiguration>empty();
}
String consortiumId = userTenants.getJsonObject(0).getString(CONSORTIUM_ID_FIELD);
String centralTenantId = userTenants.getJsonObject(0).getString(CENTRAL_TENANT_ID_FIELD);
logger.debug("Found centralTenantId: {} and consortiumId: {}", centralTenantId, consortiumId);
return Optional.of(new ConsortiumConfiguration(centralTenantId, consortiumId));
}).toCompletionStage().toCompletableFuture();
}

}
Loading

0 comments on commit d2cfce1

Please sign in to comment.