Skip to content

Commit

Permalink
Merge pull request #1519 from folio-org/tmp-release-24.3.2
Browse files Browse the repository at this point in the history
CIRC-2191 Release 24.3.2
  • Loading branch information
roman-barannyk authored Nov 30, 2024
2 parents 6892871 + 3e93891 commit 6b4d0cf
Show file tree
Hide file tree
Showing 89 changed files with 2,018 additions and 517 deletions.
19 changes: 19 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
## 24.3.2 2024-11-30
* Add mod-settings permission blocks (CIRC-2185)
* Fix automated patron blocks permission issue (CIRC-2185)
* Remove new mod-settings permissions (CIRC-2183)
* Fetch TLR settings from mod-config as fallback (CIRC-2171)
* Update API versions (CIRC-2153)
* Change ECS Primary request validation (CIRC-2151)
* Allow operation replace for instance with no items (CIRC-2137)
* Search title-level requests by both `itemId` and `instanceId` during check-in and check-out (CIRC-2125)
* Allowed SP endpoint should support `patronGroupId` parameter (CIRC-2116)
* Return empty result when search doesn't find anything (CIRC-2117)
* Pass additional `includeRoutingServicePoints` parameter when needed (CIRC-2109)
* Fetch item details across tenants (CIRC-2101)
* Create a facade for instance search (CIRC-2072)
* Fetch TLR settings from mod-settings (CIRC-2081)
* Add `ecsRequestRouting` parameter to allowed-service-points (CIRC-2051)
* Fix snapshot version (CIRC-2161)
* Review and cleanup Module Descriptors for mod-circulation (CIRC-2139)

## 24.3.1 2024-11-27

* Patron notices for the trigger “Item recalled” not sent if the item is not 1st in the title request queue (CIRC-2168)
Expand Down
314 changes: 208 additions & 106 deletions descriptors/ModuleDescriptor-template.json

Large diffs are not rendered by default.

32 changes: 30 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>mod-circulation</artifactId>
<groupId>org.folio</groupId>
<version>24.3.2-SNAPSHOT</version>
<version>24.3.3-SNAPSHOT</version>
<licenses>
<license>
<name>Apache License 2.0</name>
Expand Down Expand Up @@ -33,6 +33,9 @@
<lombok.version>1.18.28</lombok.version>
<spring.version>6.1.5</spring.version>
<maven.site.plugin.version>3.9.1</maven.site.plugin.version>

<!--Folio dependencies properties-->
<folio-module-descriptor-validator.version>1.0.1</folio-module-descriptor-validator.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -300,7 +303,7 @@
<url>https://github.com/folio-org/mod-inventory</url>
<connection>scm:git:git://github.com:folio-org/mod-inventory.git</connection>
<developerConnection>scm:git:[email protected]:folio-org/mod-inventory.git</developerConnection>
<tag>v24.3.0</tag>
<tag>HEAD</tag>
</scm>

<build>
Expand Down Expand Up @@ -518,6 +521,21 @@
<generateBackupPoms>false</generateBackupPoms>
</configuration>
</plugin>
<plugin>
<groupId>org.folio</groupId>
<artifactId>folio-module-descriptor-validator</artifactId>
<version>${folio-module-descriptor-validator.version}</version>
<executions>
<execution>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
<configuration>
<failOnInvalidDescriptor>false</failOnInvalidDescriptor>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
Expand All @@ -529,4 +547,14 @@
</plugin>
</plugins>
</reporting>

<pluginRepositories>
<pluginRepository>
<id>folio-nexus</id>
<name>FOLIO Maven repository</name>
<url>https://repository.folio.org/repository/maven-folio</url>
</pluginRepository>
</pluginRepositories>

</project>

8 changes: 8 additions & 0 deletions ramls/circulation.raml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,14 @@ resourceTypes:
description: "Instance ID"
pattern: "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[1-5][a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$"
required: false
useStubItem:
description: "When true, allows to apply circulation rules based on patron group only"
type: boolean
required: false
ecsRequestRouting:
description: "When true, returns only service points with ecsRequestRouting"
type: boolean
required: false
responses:
200:
description: "List of allowed service points was retrieved successfully"
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/folio/circulation/CirculationVerticle.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.folio.circulation.resources.FeeFineNotRealTimeScheduledNoticeProcessingResource;
import org.folio.circulation.resources.FeeFineScheduledNoticeProcessingResource;
import org.folio.circulation.resources.HealthResource;
import org.folio.circulation.resources.ItemsByInstanceResource;
import org.folio.circulation.resources.ItemsInTransitResource;
import org.folio.circulation.resources.LoanAnonymizationResource;
import org.folio.circulation.resources.LoanCirculationRulesEngineResource;
Expand Down Expand Up @@ -94,6 +95,7 @@ public void start(Promise<Void> startFuture) {
new RequestCollectionResource(client).register(router);
new RequestQueueResource(client).register(router);
new RequestByInstanceIdResource(client).register(router);
new ItemsByInstanceResource(client).register(router);

new RequestHoldShelfClearanceResource(
"/circulation/requests-reports/hold-shelf-clearance/:servicePointId", client)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ public class AllowedServicePointsRequest {

private Request.Operation operation;
private String requesterId;
private String patronGroupId;
private String instanceId;
private String itemId;
private String requestId;
private boolean useStubItem;
private boolean ecsRequestRouting;

public boolean isForTitleLevelRequest() {
return instanceId != null;
Expand All @@ -27,7 +31,6 @@ public boolean isForTitleLevelRequest() {
public boolean isForItemLevelRequest() {
return itemId != null;
}
private String requestId;

public AllowedServicePointsRequest updateWithRequestInformation(Request request) {
log.debug("updateWithRequestInformation:: parameters request: {}", request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ private CompletableFuture<Result<RequestAndRelatedRecords>> checkPolicy(
boolean tlrFeatureEnabled = request.getTlrSettingsConfiguration().isTitleLevelRequestsFeatureEnabled();

if (tlrFeatureEnabled && request.isTitleLevel() && request.isHold()) {
if (request.getEcsRequestPhase() == EcsRequestPhase.PRIMARY) {
log.warn("checkPolicy:: ECS TLR primary Hold detected, skipping policy check");
return ofAsync(() -> records);
}

log.info("checkPolicy:: checking policy for title-level hold");
return completedFuture(checkPolicyForTitleLevelHold(records));
}
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/org/folio/circulation/domain/EcsRequestPhase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.folio.circulation.domain;

import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;

import java.util.Arrays;

public enum EcsRequestPhase {
NONE(""),
PRIMARY("Primary"),
SECONDARY("Secondary");

public final String value;

public static EcsRequestPhase from(String value) {
return Arrays.stream(values())
.filter(status -> status.nameMatches(value))
.findFirst()
.orElse(NONE);
}

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

public String getValue() {
return value;
}

public boolean nameMatches(String value) {
return equalsIgnoreCase(getValue(), value);
}

@Override
public String toString() {
return value;
}
}
11 changes: 11 additions & 0 deletions src/main/java/org/folio/circulation/domain/Item.java
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,17 @@ public String getDcbItemTitle() {
return getProperty(itemRepresentation, "instanceTitle");
}

public String getTenantId() {
return getProperty(itemRepresentation, "tenantId");
}

public Item changeTenantId(String tenantId) {
if (itemRepresentation != null) {
write(itemRepresentation, "tenantId", tenantId);
}
return this;
}

public boolean isAtLocation(String locationCode) {
return locationCode != null && getLocation() != null && (
locationCode.equals(getLocation().getCode()) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.apache.logging.log4j.Logger;
import org.folio.circulation.domain.validation.RequestLoanValidator;
import org.folio.circulation.infrastructure.storage.ConfigurationRepository;
import org.folio.circulation.infrastructure.storage.SettingsRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestPolicyRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestQueueRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestRepository;
Expand All @@ -27,13 +28,14 @@ public class MoveRequestService {
private final ConfigurationRepository configurationRepository;
private final EventPublisher eventPublisher;
private final RequestQueueRepository requestQueueRepository;
private final SettingsRepository settingsRepository;
private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass());

public MoveRequestService(RequestRepository requestRepository, RequestPolicyRepository requestPolicyRepository,
UpdateUponRequest updateUponRequest, MoveRequestProcessAdapter moveRequestHelper,
RequestLoanValidator requestLoanValidator, RequestNoticeSender requestNoticeSender,
ConfigurationRepository configurationRepository, EventPublisher eventPublisher,
RequestQueueRepository requestQueueRepository) {
RequestQueueRepository requestQueueRepository, SettingsRepository settingsRepository) {

this.requestRepository = requestRepository;
this.requestPolicyRepository = requestPolicyRepository;
Expand All @@ -44,11 +46,12 @@ public MoveRequestService(RequestRepository requestRepository, RequestPolicyRepo
this.configurationRepository = configurationRepository;
this.eventPublisher = eventPublisher;
this.requestQueueRepository = requestQueueRepository;
this.settingsRepository = settingsRepository;
}

public CompletableFuture<Result<RequestAndRelatedRecords>> moveRequest(
RequestAndRelatedRecords requestAndRelatedRecords, Request originalRequest) {
return configurationRepository.lookupTlrSettings()
return settingsRepository.lookupTlrSettings()
.thenApply(r -> r.map(requestAndRelatedRecords::withTlrSettings))
.thenApply(r -> r.next(RequestServiceUtility::refuseTlrProcessingWhenFeatureIsDisabled))
.thenApply(r -> r.next(records -> RequestServiceUtility.refuseMovingToOrFromHoldTlr(records,
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/folio/circulation/domain/Request.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static org.folio.circulation.domain.representations.RequestProperties.CANCELLATION_REASON_NAME;
import static org.folio.circulation.domain.representations.RequestProperties.CANCELLATION_REASON_PUBLIC_DESCRIPTION;
import static org.folio.circulation.domain.representations.RequestProperties.ITEM_LOCATION_CODE;
import static org.folio.circulation.domain.representations.RequestProperties.ECS_REQUEST_PHASE;
import static org.folio.circulation.domain.representations.RequestProperties.HOLDINGS_RECORD_ID;
import static org.folio.circulation.domain.representations.RequestProperties.HOLD_SHELF_EXPIRATION_DATE;
import static org.folio.circulation.domain.representations.RequestProperties.INSTANCE_ID;
Expand Down Expand Up @@ -269,6 +270,10 @@ public RequestType getRequestType() {
return RequestType.from(getProperty(requestRepresentation, REQUEST_TYPE));
}

public EcsRequestPhase getEcsRequestPhase() {
return EcsRequestPhase.from(getProperty(requestRepresentation, ECS_REQUEST_PHASE));
}

boolean allowedForItem() {
return RequestTypeItemStatusWhiteList.canCreateRequestForItem(getItem().getStatus(), getRequestType());
}
Expand Down
50 changes: 50 additions & 0 deletions src/main/java/org/folio/circulation/domain/SearchInstance.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.folio.circulation.domain;

import static org.folio.circulation.support.json.JsonObjectArrayPropertyFetcher.mapToList;
import static org.folio.circulation.support.json.JsonPropertyWriter.write;

import java.lang.invoke.MethodHandles;
import java.util.Collection;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.folio.circulation.domain.representations.ItemSummaryRepresentation;
import org.folio.circulation.storage.mappers.ItemMapper;

import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import lombok.NonNull;
import lombok.ToString;
import lombok.Value;

@Value
@ToString(onlyExplicitlyIncluded = true)
public class SearchInstance {

private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass());
JsonObject representation;
String id;
@NonNull Collection<Item> items;

public static SearchInstance from(JsonObject representation) {
return new SearchInstance(representation, representation.getString("id"), mapItems(representation));
}

private static List<Item> mapItems(JsonObject representation) {
return mapToList(representation, "items", new ItemMapper()::toDomain);
}

public SearchInstance changeItems(Collection<Item> items) {
JsonArray itemsArray = new JsonArray();
for (Item item : items) {
itemsArray.add(new ItemSummaryRepresentation().createItemSummary(item));
}
write(representation, "items", itemsArray);
return new SearchInstance(representation, id, items);
}

public JsonObject toJson() {
return representation;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@

import io.vertx.core.json.JsonObject;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;

@AllArgsConstructor
@Getter
@ToString(onlyExplicitlyIncluded = true)
@EqualsAndHashCode
public class TlrSettingsConfiguration {
protected static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@
@RequiredArgsConstructor
public enum OverridableBlockType {
PATRON_BLOCK("patronBlock",
OkapiPermissions.of("circulation.override-patron-block")),
OkapiPermissions.of("circulation.override-patron-block.post")),
ITEM_LIMIT_BLOCK("itemLimitBlock",
OkapiPermissions.of("circulation.override-item-limit-block")),
OkapiPermissions.of("circulation.override-item-limit-block.post")),
ITEM_NOT_LOANABLE_BLOCK("itemNotLoanableBlock",
OkapiPermissions.of("circulation.override-item-not-loanable-block")),
OkapiPermissions.of("circulation.override-item-not-loanable-block.post")),
RENEWAL_BLOCK("renewalBlock",
OkapiPermissions.of("circulation.override-renewal-block")),
OkapiPermissions.of("circulation.override-renewal-block.post")),
RENEWAL_DUE_DATE_REQUIRED_BLOCK("renewalDueDateRequiredBlock",
OkapiPermissions.of("circulation.override-renewal-block"));
OkapiPermissions.of("circulation.override-renewal-block.post"));

private final String name;
private final OkapiPermissions requiredOverridePermissions;

public OkapiPermissions getMissingOverridePermissions(OkapiPermissions existingPermissions) {
return requiredOverridePermissions.getAllNotContainedIn(existingPermissions);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public JsonObject createItemSummary(Item item) {
write(itemSummary, "copyNumber", item.getCopyNumber());
write(itemSummary, CALL_NUMBER_COMPONENTS,
createCallNumberComponents(item.getCallNumberComponents()));
write(itemSummary, "tenantId", item.getTenantId());

JsonObject status = new JsonObject()
.put("name", item.getStatus().getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ private RequestProperties() { }
public static final String HOLDINGS_RECORD_ID = "holdingsRecordId";
public static final String REQUEST_LEVEL = "requestLevel";
public static final String REQUEST_TYPE = "requestType";
public static final String ECS_REQUEST_PHASE = "ecsRequestPhase";
public static final String PROXY_USER_ID = "proxyUserId";
public static final String POSITION = "position";
public static final String HOLD_SHELF_EXPIRATION_DATE = "holdShelfExpirationDate";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import org.folio.circulation.support.results.Result;

import io.vertx.core.json.JsonObject;
import lombok.extern.log4j.Log4j2;

@Log4j2
public class ConfigurationRepository {
private static final String CONFIGS_KEY = "configs";
private static final String MODULE_NAME_KEY = "module";
Expand Down Expand Up @@ -50,6 +52,7 @@ public CompletableFuture<Result<Integer>> lookupSessionTimeout() {
}

public CompletableFuture<Result<TlrSettingsConfiguration>> lookupTlrSettings() {
log.info("lookupTlrSettings:: fetching TLR configuration");
Result<CqlQuery> queryResult = defineModuleNameAndConfigNameFilter(
"SETTINGS", "TLR");

Expand Down
Loading

0 comments on commit 6b4d0cf

Please sign in to comment.