From 96b560756e0193fef4cd7583a7941cbe41ea9dc4 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Tue, 2 Jul 2024 13:34:45 +0530 Subject: [PATCH 01/38] CIRC-2099 POST Api implementation --- descriptors/ModuleDescriptor-template.json | 25 ++++++++ ramls/print-events-request.json | 38 ++++++++++++ ramls/print-events.raml | 47 +++++++++++++++ .../circulation/CirculationVerticle.java | 2 + .../circulation/domain/PrintEventRequest.java | 59 +++++++++++++++++++ .../storage/PrintEventsRepository.java | 35 +++++++++++ .../resources/PrintEventsResource.java | 47 +++++++++++++++ .../folio/circulation/support/Clients.java | 15 +++++ .../api/printEvents/PrintEventsTests.java | 34 +++++++++++ src/test/java/api/support/APITests.java | 3 + .../java/api/support/fakes/FakeOkapi.java | 5 ++ .../java/api/support/http/InterfaceUrls.java | 4 ++ .../java/api/support/http/ResourceClient.java | 4 ++ 13 files changed, 318 insertions(+) create mode 100644 ramls/print-events-request.json create mode 100644 ramls/print-events.raml create mode 100644 src/main/java/org/folio/circulation/domain/PrintEventRequest.java create mode 100644 src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java create mode 100644 src/main/java/org/folio/circulation/resources/PrintEventsResource.java create mode 100644 src/test/java/api/printEvents/PrintEventsTests.java diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 37fcbce920..178dca4dd6 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -737,6 +737,22 @@ } ] }, + { + "id": "print-events", + "version": "1.0", + "handlers": [ + { + "methods": ["POST"], + "pathPattern": "/circulation/print-events", + "permissionsRequired": [ + "circulation.print-events.post" + ], + "modulePermissions": [ + "circulation-storage.print-events.post" + ] + } + ] + }, { "id": "_timer", "version": "1.0", @@ -1318,6 +1334,10 @@ { "id": "circulation-settings-storage", "version": "1.0" + }, + { + "id": "print-events-storage", + "version": "1.0" } ], "optional": [ @@ -1327,6 +1347,11 @@ } ], "permissionSets": [ + { + "permissionName": "circulation.print-events.post", + "displayName": "circulation - create print events", + "description": "create print event logs" + }, { "permissionName": "circulation.requests.queue.reorder.collection.post", "displayName": "circulation - reorder queue for an item", diff --git a/ramls/print-events-request.json b/ramls/print-events-request.json new file mode 100644 index 0000000000..12d0d6d389 --- /dev/null +++ b/ramls/print-events-request.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Print Events Request", + "type": "object", + "properties": { + "requestIds": { + "description": "List of request IDs", + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "requesterId": { + "description": "ID of the requester", + "type": "string", + "minLength": 1, + "pattern": "^(?!\\s*$).+" + }, + "requesterName": { + "description": "Name of the requester", + "type": "string", + "minLength": 1, + "pattern": "^(?!\\s*$).+" + }, + "printEventDate": { + "description": "Date and time when the print command is executed", + "type": "string", + "format": "date-time" + } + }, + "required": [ + "requestIds", + "requesterId", + "requesterName", + "printEventDate" + ] +} diff --git a/ramls/print-events.raml b/ramls/print-events.raml new file mode 100644 index 0000000000..cf8b36c63f --- /dev/null +++ b/ramls/print-events.raml @@ -0,0 +1,47 @@ +#%RAML 1.0 +title: Print Events +version: v1.0 +protocols: [ HTTP, HTTPS ] +baseUri: http://localhost:9130 + +documentation: + - title: Print Events API + content: Api for print events + +types: + print-events-request: !include print-events-request.json + errors: !include raml-util/schemas/errors.schema + +traits: + validate: !include raml-util/traits/validation.raml + +/circulation/print-events: + post: + is: [validate] + description: save a print event log + body: + application/json: + type: print-events-request + responses: + 201: + description: "All items have been successfully created or updated" + 409: + description: "Optimistic locking version conflict" + body: + text/plain: + example: "version error" + 413: + description: "Payload Too Large" + body: + text/plain: + example: "Payload Too Large" + 422: + description: "Unprocessable Entity" + body: + application/json: + type: errors + 500: + description: "Internal server error" + body: + text/plain: + example: "Internal server error" diff --git a/src/main/java/org/folio/circulation/CirculationVerticle.java b/src/main/java/org/folio/circulation/CirculationVerticle.java index f0d2371440..4956ddb53a 100644 --- a/src/main/java/org/folio/circulation/CirculationVerticle.java +++ b/src/main/java/org/folio/circulation/CirculationVerticle.java @@ -31,6 +31,7 @@ import org.folio.circulation.resources.OverdueFineCirculationRulesEngineResource; import org.folio.circulation.resources.OverdueFineScheduledNoticeProcessingResource; import org.folio.circulation.resources.PickSlipsResource; +import org.folio.circulation.resources.PrintEventsResource; import org.folio.circulation.resources.RequestByInstanceIdResource; import org.folio.circulation.resources.RequestCirculationRulesEngineResource; import org.folio.circulation.resources.RequestCollectionResource; @@ -152,6 +153,7 @@ public void start(Promise startFuture) { new LoanRelatedFeeFineClosedHandlerResource(client).register(router); new FeeFineBalanceChangedHandlerResource(client).register(router); new CirculationSettingsResource(client).register(router); + new PrintEventsResource(client).register(router); server.requestHandler(router) .listen(config().getInteger("port"), result -> { diff --git a/src/main/java/org/folio/circulation/domain/PrintEventRequest.java b/src/main/java/org/folio/circulation/domain/PrintEventRequest.java new file mode 100644 index 0000000000..0145f4256b --- /dev/null +++ b/src/main/java/org/folio/circulation/domain/PrintEventRequest.java @@ -0,0 +1,59 @@ +package org.folio.circulation.domain; + +import io.vertx.core.json.JsonObject; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.invoke.MethodHandles; +import java.util.List; +import java.util.Set; + +import static lombok.AccessLevel.PRIVATE; +import static org.folio.circulation.support.json.JsonPropertyFetcher.getArrayProperty; +import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; + +@AllArgsConstructor(access = PRIVATE) +@ToString(onlyExplicitlyIncluded = true) +public class PrintEventRequest { + private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); + public static final String REQUEST_IDS_FIELD = "requestIds"; + public static final String REQUESTER_ID_FIELD = "requesterId"; + public static final String REQUESTER_NAME_FIELD = "requesterName"; + public static final String PRINT_DATE_FIELD = "printEventDate"; + + @ToString.Include + @Getter + private final JsonObject representation; + + @Getter + private final List requestIds; + @Getter + private final String requesterId; + @Getter + private final String requesterName; + @Getter + private final String printEventDate; + + public static PrintEventRequest from(JsonObject representation) { + final var requestIds = getArrayProperty(representation, REQUEST_IDS_FIELD).stream() + .map(String.class::cast) + .toList(); + final var requesterId = getProperty(representation, REQUESTER_ID_FIELD); + final var requesterName = getProperty(representation, REQUESTER_NAME_FIELD); + final var printEventDate = getProperty(representation, PRINT_DATE_FIELD); + + if (requestIds.isEmpty() || null == requesterId || null == requesterName || null == printEventDate || !containsOnlyKnownFields(representation)) { + log.info("from:: Print Event Request JSON is invalid: {},{},{},{},{}", representation, requestIds, requesterName, requesterId, printEventDate); + return null; + } + return new PrintEventRequest(representation, requestIds, requesterId, requesterName, printEventDate); + } + + private static boolean containsOnlyKnownFields(JsonObject representation) { + return Set.of(REQUEST_IDS_FIELD, REQUESTER_ID_FIELD, REQUESTER_NAME_FIELD, PRINT_DATE_FIELD) + .containsAll(representation.fieldNames()); + } +} diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java new file mode 100644 index 0000000000..1a179857ff --- /dev/null +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -0,0 +1,35 @@ +package org.folio.circulation.infrastructure.storage; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.folio.circulation.domain.PrintEventRequest; +import org.folio.circulation.support.Clients; +import org.folio.circulation.support.CollectionResourceClient; +import org.folio.circulation.support.http.client.ResponseInterpreter; +import org.folio.circulation.support.results.Result; + +import java.lang.invoke.MethodHandles; +import java.util.concurrent.CompletableFuture; + +import static org.folio.circulation.support.http.ResponseMapping.forwardOnFailure; +import static org.folio.circulation.support.results.Result.succeeded; + +public class PrintEventsRepository { + private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); + + private final CollectionResourceClient printEventsStorageClient; + + public PrintEventsRepository(Clients clients) { + printEventsStorageClient = clients.printEventsStorageClient(); + } + + public CompletableFuture> create(PrintEventRequest printEventRequest) { + log.info("create:: parameters printEvent: {}", printEventRequest); + final var storagePrintEventRequest = printEventRequest.getRepresentation(); + final ResponseInterpreter interpreter = new ResponseInterpreter() + .on(201, succeeded(null)) + .otherwise(forwardOnFailure()); + return printEventsStorageClient.post(storagePrintEventRequest).thenApply(interpreter::flatMap); + } + +} diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java new file mode 100644 index 0000000000..e284206b0d --- /dev/null +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -0,0 +1,47 @@ +package org.folio.circulation.resources; + +import io.vertx.core.http.HttpClient; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.folio.circulation.domain.PrintEventRequest; +import org.folio.circulation.infrastructure.storage.PrintEventsRepository; +import org.folio.circulation.support.Clients; +import org.folio.circulation.support.RouteRegistration; +import org.folio.circulation.support.http.server.JsonHttpResponse; +import org.folio.circulation.support.http.server.WebContext; + +import java.lang.invoke.MethodHandles; + +import static org.folio.circulation.support.results.Result.ofAsync; + +public class PrintEventsResource extends Resource { + private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); + + public PrintEventsResource(HttpClient client) { + super(client); + } + + @Override + public void register(Router router) { + new RouteRegistration("/circulation/print-events", router) + .create(this::create); + } + + void create(RoutingContext routingContext) { + final var context = new WebContext(routingContext); + final var clients = Clients.create(context, client); + final var printEventsRepository = new PrintEventsRepository(clients); + + final var incomingRepresentation = routingContext.body().asJsonObject(); + final var printEventRequest = PrintEventRequest.from(incomingRepresentation); + + log.info("create:: Creating print event: {}", () -> printEventRequest); + + ofAsync(printEventRequest) + .thenCompose(r -> r.after(printEventsRepository::create)) + .thenApply(r -> r.map(response -> JsonHttpResponse.created(null, null))) + .thenAccept(context::writeResultToHttpResponse); + } +} diff --git a/src/main/java/org/folio/circulation/support/Clients.java b/src/main/java/org/folio/circulation/support/Clients.java index 404b433461..78cd6271dc 100644 --- a/src/main/java/org/folio/circulation/support/Clients.java +++ b/src/main/java/org/folio/circulation/support/Clients.java @@ -70,6 +70,8 @@ public class Clients { private final CollectionResourceClient circulationItemClient; private final GetManyRecordsClient settingsStorageClient; private final CollectionResourceClient circulationSettingsStorageClient; + private final CollectionResourceClient printEventsStorageClient; + public static Clients create(WebContext context, HttpClient httpClient) { return new Clients(context.createHttpClient(httpClient), context); @@ -138,6 +140,8 @@ private Clients(OkapiHttpClient client, WebContext context) { settingsStorageClient = createSettingsStorageClient(client, context); circulationItemClient = createCirculationItemClient(client, context); circulationSettingsStorageClient = createCirculationSettingsStorageClient(client, context); + printEventsStorageClient = createPrintEventsStorageClient(client, context); + } catch(MalformedURLException e) { throw new InvalidOkapiLocationException(context.getOkapiLocation(), e); @@ -380,6 +384,10 @@ public CollectionResourceClient circulationSettingsStorageClient() { return circulationSettingsStorageClient; } + public CollectionResourceClient printEventsStorageClient() { + return printEventsStorageClient; + } + private static CollectionResourceClient getCollectionResourceClient( OkapiHttpClient client, WebContext context, String path) @@ -814,6 +822,13 @@ private CollectionResourceClient createCirculationSettingsStorageClient( "/circulation-settings-storage/circulation-settings"); } + private CollectionResourceClient createPrintEventsStorageClient( + OkapiHttpClient client, WebContext context) throws MalformedURLException { + + return getCollectionResourceClient(client, context, + "/print-events-storage/print-events"); + } + private GetManyRecordsClient createSettingsStorageClient( OkapiHttpClient client, WebContext context) throws MalformedURLException { diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java new file mode 100644 index 0000000000..744f36db5c --- /dev/null +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -0,0 +1,34 @@ +package api.printEvents; + +import api.support.APITests; +import io.vertx.core.json.JsonObject; +import org.folio.circulation.support.http.client.Response; +import org.hamcrest.core.Is; +import org.junit.jupiter.api.Test; + +import java.net.HttpURLConnection; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; + + class PrintEventsTests extends APITests { + public static final String REQUEST_IDS_FIELD = "requestIds"; + public static final String REQUESTER_ID_FIELD = "requesterId"; + public static final String REQUESTER_NAME_FIELD = "requesterName"; + public static final String PRINT_DATE_FIELD = "printEventDate"; + + @Test + void postPrintEventsTest() { + JsonObject printRequest = getPrintEvent(); + Response response = printEventsClient.attemptCreate(printRequest); + assertThat(response.getStatusCode(), Is.is(HttpURLConnection.HTTP_CREATED)); + } + private JsonObject getPrintEvent() { + List requestIds = List.of("request1", "request2"); + return new JsonObject() + .put(REQUEST_IDS_FIELD, requestIds) + .put(REQUESTER_ID_FIELD, "sample") + .put(REQUESTER_NAME_FIELD, "Sample Requester") + .put(PRINT_DATE_FIELD, "2024-06-25T14:30:00Z"); + } +} diff --git a/src/test/java/api/support/APITests.java b/src/test/java/api/support/APITests.java index b872ce7165..6935d04e64 100644 --- a/src/test/java/api/support/APITests.java +++ b/src/test/java/api/support/APITests.java @@ -197,6 +197,9 @@ public abstract class APITests { protected final ResourceClient circulationSettingsClient = ResourceClient.forCirculationSettings(); + protected final ResourceClient printEventsClient = + ResourceClient.forPrintEvents(); + protected final ServicePointsFixture servicePointsFixture = new ServicePointsFixture(servicePointsClient); diff --git a/src/test/java/api/support/fakes/FakeOkapi.java b/src/test/java/api/support/fakes/FakeOkapi.java index 5cbecb8542..1275386fa4 100644 --- a/src/test/java/api/support/fakes/FakeOkapi.java +++ b/src/test/java/api/support/fakes/FakeOkapi.java @@ -422,6 +422,11 @@ public void start(Promise startFuture) throws IOException { .withChangeMetadata() .create().register(router); + new FakeStorageModuleBuilder() + .withRootPath("/print-events-storage/print-events") + .withChangeMetadata() + .create().register(router); + new FakeFeeFineOperationsModule().register(router); server.requestHandler(router) diff --git a/src/test/java/api/support/http/InterfaceUrls.java b/src/test/java/api/support/http/InterfaceUrls.java index 59d35de534..f85577d3a6 100644 --- a/src/test/java/api/support/http/InterfaceUrls.java +++ b/src/test/java/api/support/http/InterfaceUrls.java @@ -337,4 +337,8 @@ public static URL settingsStorageUrl() { public static URL circulationSettingsUrl(String subPath) { return circulationModuleUrl("/circulation/settings" + subPath); } + + public static URL printEventsUrl(String subPath) { + return circulationModuleUrl("/circulation/print-events" + subPath); + } } diff --git a/src/test/java/api/support/http/ResourceClient.java b/src/test/java/api/support/http/ResourceClient.java index 8e9b7d63be..73893b3b33 100644 --- a/src/test/java/api/support/http/ResourceClient.java +++ b/src/test/java/api/support/http/ResourceClient.java @@ -276,6 +276,10 @@ public static ResourceClient forCirculationSettings() { return new ResourceClient(InterfaceUrls::circulationSettingsUrl, "circulationSettings"); } + public static ResourceClient forPrintEvents() { + return new ResourceClient(InterfaceUrls::printEventsUrl, " "); + } + private ResourceClient(UrlMaker urlMaker, String collectionArrayPropertyName) { this.urlMaker = urlMaker; this.collectionArrayPropertyName = collectionArrayPropertyName; From ee8f0815ebb4b9d92053b8c6930bb845ddb298b4 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Wed, 3 Jul 2024 13:57:52 +0530 Subject: [PATCH 02/38] CIRC-2099 POST Api implementation --- .../resources/PrintEventsResource.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index e284206b0d..c18fbe6f96 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -11,10 +11,14 @@ import org.folio.circulation.support.RouteRegistration; import org.folio.circulation.support.http.server.JsonHttpResponse; import org.folio.circulation.support.http.server.WebContext; +import org.folio.circulation.support.results.Result; import java.lang.invoke.MethodHandles; +import java.util.function.Function; +import static org.folio.circulation.support.ValidationErrorFailure.singleValidationError; import static org.folio.circulation.support.results.Result.ofAsync; +import static org.folio.circulation.support.results.Result.succeeded; public class PrintEventsResource extends Resource { private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); @@ -40,8 +44,18 @@ void create(RoutingContext routingContext) { log.info("create:: Creating print event: {}", () -> printEventRequest); ofAsync(printEventRequest) + .thenApply(refuseWhenPrintEventRequestIsInvalid()) .thenCompose(r -> r.after(printEventsRepository::create)) - .thenApply(r -> r.map(response -> JsonHttpResponse.created(null, null))) + .thenApply(r -> r.map(response -> { + assert printEventRequest != null; + return JsonHttpResponse.created(printEventRequest.getRepresentation(), null); + })) .thenAccept(context::writeResultToHttpResponse); } + + private static Function, Result> + refuseWhenPrintEventRequestIsInvalid() { + return r -> r.failWhen(printEventRequest -> succeeded(printEventRequest == null), + circulationSetting -> singleValidationError("Print Event Request JSON is invalid", "", "")); + } } From 57b915678b19e540cce82ba4172254e5c6c02135 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Wed, 3 Jul 2024 17:45:07 +0530 Subject: [PATCH 03/38] CIRC-2099 POST Api implementation --- .../org/folio/circulation/resources/PrintEventsResource.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index c18fbe6f96..22f9e64626 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -37,11 +37,10 @@ void create(RoutingContext routingContext) { final var context = new WebContext(routingContext); final var clients = Clients.create(context, client); final var printEventsRepository = new PrintEventsRepository(clients); - final var incomingRepresentation = routingContext.body().asJsonObject(); final var printEventRequest = PrintEventRequest.from(incomingRepresentation); - log.info("create:: Creating print event: {}", () -> printEventRequest); + log.info("create:: Creating print event: {}", printEventRequest); ofAsync(printEventRequest) .thenApply(refuseWhenPrintEventRequestIsInvalid()) From 6fd68143a7ad3576eaab39d0026456d2a480865c Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Thu, 4 Jul 2024 14:25:44 +0530 Subject: [PATCH 04/38] CIRC-2099 Modified TestClass --- .../api/printEvents/PrintEventsTests.java | 52 ++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index 744f36db5c..95e70421df 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -3,32 +3,60 @@ import api.support.APITests; import io.vertx.core.json.JsonObject; import org.folio.circulation.support.http.client.Response; -import org.hamcrest.core.Is; import org.junit.jupiter.api.Test; -import java.net.HttpURLConnection; import java.util.List; +import static api.support.matchers.ResponseStatusCodeMatcher.hasStatus; +import static org.folio.HttpStatus.HTTP_CREATED; +import static org.folio.HttpStatus.HTTP_UNPROCESSABLE_ENTITY; import static org.hamcrest.MatcherAssert.assertThat; - class PrintEventsTests extends APITests { +class PrintEventsTests extends APITests { public static final String REQUEST_IDS_FIELD = "requestIds"; public static final String REQUESTER_ID_FIELD = "requesterId"; public static final String REQUESTER_NAME_FIELD = "requesterName"; public static final String PRINT_DATE_FIELD = "printEventDate"; + public static final String INVALID_FIELD = "invalidField"; @Test void postPrintEventsTest() { JsonObject printRequest = getPrintEvent(); Response response = printEventsClient.attemptCreate(printRequest); - assertThat(response.getStatusCode(), Is.is(HttpURLConnection.HTTP_CREATED)); + assertThat(response, hasStatus(HTTP_CREATED)); + } + + @Test + void postPrintEventsWithInvalidField() { + JsonObject printRequest = getPrintEvent(); + printRequest.put(INVALID_FIELD, "invalid"); + Response response = printEventsClient.attemptCreate(printRequest); + assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); + } + + @Test + void postPrintEventsWithInvalidField_EmptyRequestIdsList() { + JsonObject printRequest = getPrintEvent(); + List requestIds = List.of(); + printRequest.put(REQUEST_IDS_FIELD, requestIds); + Response response = printEventsClient.attemptCreate(printRequest); + assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); + } + + @Test + void postPrintEventsWithInvalidField_NullFeild() { + JsonObject printRequest = getPrintEvent(); + printRequest.put(REQUESTER_ID_FIELD, null); + Response response = printEventsClient.attemptCreate(printRequest); + assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); + } + + private JsonObject getPrintEvent() { + List requestIds = List.of("request1", "request2"); + return new JsonObject() + .put(REQUEST_IDS_FIELD, requestIds) + .put(REQUESTER_ID_FIELD, "sreeja") + .put(REQUESTER_NAME_FIELD, "Sample Requester") + .put(PRINT_DATE_FIELD, "2024-06-25T14:30:00Z"); } - private JsonObject getPrintEvent() { - List requestIds = List.of("request1", "request2"); - return new JsonObject() - .put(REQUEST_IDS_FIELD, requestIds) - .put(REQUESTER_ID_FIELD, "sample") - .put(REQUESTER_NAME_FIELD, "Sample Requester") - .put(PRINT_DATE_FIELD, "2024-06-25T14:30:00Z"); - } } From e342831ce780febd90a4e5d3e5db28c78f9854e3 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Thu, 4 Jul 2024 14:50:16 +0530 Subject: [PATCH 05/38] CIRC-2099 removed raml files --- ramls/print-events-request.json | 38 -------------------------- ramls/print-events.raml | 47 --------------------------------- 2 files changed, 85 deletions(-) delete mode 100644 ramls/print-events-request.json delete mode 100644 ramls/print-events.raml diff --git a/ramls/print-events-request.json b/ramls/print-events-request.json deleted file mode 100644 index 12d0d6d389..0000000000 --- a/ramls/print-events-request.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "Print Events Request", - "type": "object", - "properties": { - "requestIds": { - "description": "List of request IDs", - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - }, - "requesterId": { - "description": "ID of the requester", - "type": "string", - "minLength": 1, - "pattern": "^(?!\\s*$).+" - }, - "requesterName": { - "description": "Name of the requester", - "type": "string", - "minLength": 1, - "pattern": "^(?!\\s*$).+" - }, - "printEventDate": { - "description": "Date and time when the print command is executed", - "type": "string", - "format": "date-time" - } - }, - "required": [ - "requestIds", - "requesterId", - "requesterName", - "printEventDate" - ] -} diff --git a/ramls/print-events.raml b/ramls/print-events.raml deleted file mode 100644 index cf8b36c63f..0000000000 --- a/ramls/print-events.raml +++ /dev/null @@ -1,47 +0,0 @@ -#%RAML 1.0 -title: Print Events -version: v1.0 -protocols: [ HTTP, HTTPS ] -baseUri: http://localhost:9130 - -documentation: - - title: Print Events API - content: Api for print events - -types: - print-events-request: !include print-events-request.json - errors: !include raml-util/schemas/errors.schema - -traits: - validate: !include raml-util/traits/validation.raml - -/circulation/print-events: - post: - is: [validate] - description: save a print event log - body: - application/json: - type: print-events-request - responses: - 201: - description: "All items have been successfully created or updated" - 409: - description: "Optimistic locking version conflict" - body: - text/plain: - example: "version error" - 413: - description: "Payload Too Large" - body: - text/plain: - example: "Payload Too Large" - 422: - description: "Unprocessable Entity" - body: - application/json: - type: errors - 500: - description: "Internal server error" - body: - text/plain: - example: "Internal server error" From 17e14a97376dfe5f0bf39ac5487084befad05977 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Fri, 5 Jul 2024 17:50:56 +0530 Subject: [PATCH 06/38] CIRC-2099 changes in the root path of print-event-storage --- src/main/java/org/folio/circulation/support/Clients.java | 2 +- src/test/java/api/support/fakes/FakeOkapi.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/folio/circulation/support/Clients.java b/src/main/java/org/folio/circulation/support/Clients.java index 78cd6271dc..4f79e5836a 100644 --- a/src/main/java/org/folio/circulation/support/Clients.java +++ b/src/main/java/org/folio/circulation/support/Clients.java @@ -826,7 +826,7 @@ private CollectionResourceClient createPrintEventsStorageClient( OkapiHttpClient client, WebContext context) throws MalformedURLException { return getCollectionResourceClient(client, context, - "/print-events-storage/print-events"); + "/print-events-storage"); } private GetManyRecordsClient createSettingsStorageClient( diff --git a/src/test/java/api/support/fakes/FakeOkapi.java b/src/test/java/api/support/fakes/FakeOkapi.java index 1275386fa4..f8742a1c36 100644 --- a/src/test/java/api/support/fakes/FakeOkapi.java +++ b/src/test/java/api/support/fakes/FakeOkapi.java @@ -423,7 +423,7 @@ public void start(Promise startFuture) throws IOException { .create().register(router); new FakeStorageModuleBuilder() - .withRootPath("/print-events-storage/print-events") + .withRootPath("/print-events-storage") .withChangeMetadata() .create().register(router); From ff553747170daa8998a4880fbb677021ff24f4d4 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Mon, 8 Jul 2024 11:42:38 +0530 Subject: [PATCH 07/38] CIRC-2099 testing --- src/main/java/org/folio/circulation/support/Clients.java | 2 +- src/test/java/api/printEvents/PrintEventsTests.java | 2 +- src/test/java/api/support/fakes/FakeOkapi.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/folio/circulation/support/Clients.java b/src/main/java/org/folio/circulation/support/Clients.java index 4f79e5836a..78cd6271dc 100644 --- a/src/main/java/org/folio/circulation/support/Clients.java +++ b/src/main/java/org/folio/circulation/support/Clients.java @@ -826,7 +826,7 @@ private CollectionResourceClient createPrintEventsStorageClient( OkapiHttpClient client, WebContext context) throws MalformedURLException { return getCollectionResourceClient(client, context, - "/print-events-storage"); + "/print-events-storage/print-events"); } private GetManyRecordsClient createSettingsStorageClient( diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index 95e70421df..f27e32fbb3 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -44,7 +44,7 @@ void postPrintEventsWithInvalidField_EmptyRequestIdsList() { } @Test - void postPrintEventsWithInvalidField_NullFeild() { + void postPrintEventsWithInvalidField_NullField() { JsonObject printRequest = getPrintEvent(); printRequest.put(REQUESTER_ID_FIELD, null); Response response = printEventsClient.attemptCreate(printRequest); diff --git a/src/test/java/api/support/fakes/FakeOkapi.java b/src/test/java/api/support/fakes/FakeOkapi.java index f8742a1c36..1275386fa4 100644 --- a/src/test/java/api/support/fakes/FakeOkapi.java +++ b/src/test/java/api/support/fakes/FakeOkapi.java @@ -423,7 +423,7 @@ public void start(Promise startFuture) throws IOException { .create().register(router); new FakeStorageModuleBuilder() - .withRootPath("/print-events-storage") + .withRootPath("/print-events-storage/print-events") .withChangeMetadata() .create().register(router); From d5f82d08be66d104b75ab2eee1ba413e839793c3 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Mon, 8 Jul 2024 14:09:08 +0530 Subject: [PATCH 08/38] CIRC-2099 testing --- ramls/examples/print-events-request.json | 9 +++++++++ src/main/java/org/folio/circulation/support/Clients.java | 2 +- src/test/java/api/support/fakes/FakeOkapi.java | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 ramls/examples/print-events-request.json diff --git a/ramls/examples/print-events-request.json b/ramls/examples/print-events-request.json new file mode 100644 index 0000000000..8505827a64 --- /dev/null +++ b/ramls/examples/print-events-request.json @@ -0,0 +1,9 @@ +{ + "requestIds": [ + "059e54bb-53e5-4039-a2fb-b34358e88b0a", + "e70dcbae-30c6-47ac-94f8-4ffefd44a935" + ], + "requesterId": "d51470ea-5daa-480b-a4aa-09c8c6d9940e", + "requesterName": "requester", + "printEventDate": "2024-06-25T20:00:00+05:30" +} diff --git a/src/main/java/org/folio/circulation/support/Clients.java b/src/main/java/org/folio/circulation/support/Clients.java index 78cd6271dc..4b1ddf594c 100644 --- a/src/main/java/org/folio/circulation/support/Clients.java +++ b/src/main/java/org/folio/circulation/support/Clients.java @@ -826,7 +826,7 @@ private CollectionResourceClient createPrintEventsStorageClient( OkapiHttpClient client, WebContext context) throws MalformedURLException { return getCollectionResourceClient(client, context, - "/print-events-storage/print-events"); + "/print-events-storage/print-events/create-batch"); } private GetManyRecordsClient createSettingsStorageClient( diff --git a/src/test/java/api/support/fakes/FakeOkapi.java b/src/test/java/api/support/fakes/FakeOkapi.java index 1275386fa4..7c3b93fcba 100644 --- a/src/test/java/api/support/fakes/FakeOkapi.java +++ b/src/test/java/api/support/fakes/FakeOkapi.java @@ -423,7 +423,7 @@ public void start(Promise startFuture) throws IOException { .create().register(router); new FakeStorageModuleBuilder() - .withRootPath("/print-events-storage/print-events") + .withRootPath("/print-events-storage/print-events/create-batch") .withChangeMetadata() .create().register(router); From 5c22e90965403685cf4e69356ea8e5341515e8a5 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Mon, 8 Jul 2024 16:45:29 +0530 Subject: [PATCH 09/38] CIRC-2099 path modified to /create-batch --- descriptors/ModuleDescriptor-template.json | 2 +- .../resources/PrintEventsResource.java | 2 +- .../api/printEvents/PrintEventsTests.java | 30 ++++++++----------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 178dca4dd6..cf16161568 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -743,7 +743,7 @@ "handlers": [ { "methods": ["POST"], - "pathPattern": "/circulation/print-events", + "pathPattern": "/circulation/print-events/create-batch", "permissionsRequired": [ "circulation.print-events.post" ], diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index 22f9e64626..358e5b0c41 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -29,7 +29,7 @@ public PrintEventsResource(HttpClient client) { @Override public void register(Router router) { - new RouteRegistration("/circulation/print-events", router) + new RouteRegistration("/circulation/print-events/create-batch", router) .create(this::create); } diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index f27e32fbb3..0d23cbda85 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -7,30 +7,26 @@ import java.util.List; +import static api.support.http.InterfaceUrls.printEventsUrl; import static api.support.matchers.ResponseStatusCodeMatcher.hasStatus; import static org.folio.HttpStatus.HTTP_CREATED; import static org.folio.HttpStatus.HTTP_UNPROCESSABLE_ENTITY; import static org.hamcrest.MatcherAssert.assertThat; class PrintEventsTests extends APITests { - public static final String REQUEST_IDS_FIELD = "requestIds"; - public static final String REQUESTER_ID_FIELD = "requesterId"; - public static final String REQUESTER_NAME_FIELD = "requesterName"; - public static final String PRINT_DATE_FIELD = "printEventDate"; - public static final String INVALID_FIELD = "invalidField"; @Test void postPrintEventsTest() { JsonObject printRequest = getPrintEvent(); - Response response = printEventsClient.attemptCreate(printRequest); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/create-batch"), "post-print-event"); assertThat(response, hasStatus(HTTP_CREATED)); } @Test void postPrintEventsWithInvalidField() { JsonObject printRequest = getPrintEvent(); - printRequest.put(INVALID_FIELD, "invalid"); - Response response = printEventsClient.attemptCreate(printRequest); + printRequest.put("invalidField", "invalid"); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/create-batch"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); } @@ -38,25 +34,25 @@ void postPrintEventsWithInvalidField() { void postPrintEventsWithInvalidField_EmptyRequestIdsList() { JsonObject printRequest = getPrintEvent(); List requestIds = List.of(); - printRequest.put(REQUEST_IDS_FIELD, requestIds); - Response response = printEventsClient.attemptCreate(printRequest); + printRequest.put("requestIds", requestIds); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/create-batch"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); } @Test void postPrintEventsWithInvalidField_NullField() { JsonObject printRequest = getPrintEvent(); - printRequest.put(REQUESTER_ID_FIELD, null); - Response response = printEventsClient.attemptCreate(printRequest); + printRequest.put("requesterId", null); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/create-batch"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); } private JsonObject getPrintEvent() { - List requestIds = List.of("request1", "request2"); + List requestIds = List.of("5f5751b4-e352-4121-adca-204b0c2aec43", "5f5751b4-e352-4121-adca-204b0c2aec44"); return new JsonObject() - .put(REQUEST_IDS_FIELD, requestIds) - .put(REQUESTER_ID_FIELD, "sreeja") - .put(REQUESTER_NAME_FIELD, "Sample Requester") - .put(PRINT_DATE_FIELD, "2024-06-25T14:30:00Z"); + .put("requestIds", requestIds) + .put("requesterId", "5f5751b4-e352-4121-adca-204b0c2aec43") + .put("requesterName", "requester") + .put("printEventDate", "2024-06-25T14:30:00Z"); } } From 14f4e4eaf42ff113c39424fc0fca603899446656 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Wed, 10 Jul 2024 12:52:21 +0530 Subject: [PATCH 10/38] CIRC-2099 path modified to /circulation/print-events-entry --- descriptors/ModuleDescriptor-template.json | 2 +- .../folio/circulation/resources/PrintEventsResource.java | 2 +- src/main/java/org/folio/circulation/support/Clients.java | 2 +- src/test/java/api/printEvents/PrintEventsTests.java | 8 ++++---- src/test/java/api/support/fakes/FakeOkapi.java | 2 +- src/test/java/api/support/http/InterfaceUrls.java | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index cf16161568..d038e74136 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -743,7 +743,7 @@ "handlers": [ { "methods": ["POST"], - "pathPattern": "/circulation/print-events/create-batch", + "pathPattern": "/circulation/print-events-entry", "permissionsRequired": [ "circulation.print-events.post" ], diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index 358e5b0c41..aa10754e8f 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -29,7 +29,7 @@ public PrintEventsResource(HttpClient client) { @Override public void register(Router router) { - new RouteRegistration("/circulation/print-events/create-batch", router) + new RouteRegistration("/circulation/print-events-entry", router) .create(this::create); } diff --git a/src/main/java/org/folio/circulation/support/Clients.java b/src/main/java/org/folio/circulation/support/Clients.java index 4b1ddf594c..99be88183c 100644 --- a/src/main/java/org/folio/circulation/support/Clients.java +++ b/src/main/java/org/folio/circulation/support/Clients.java @@ -826,7 +826,7 @@ private CollectionResourceClient createPrintEventsStorageClient( OkapiHttpClient client, WebContext context) throws MalformedURLException { return getCollectionResourceClient(client, context, - "/print-events-storage/print-events/create-batch"); + "/print-events-storage/print-events-entry"); } private GetManyRecordsClient createSettingsStorageClient( diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index 0d23cbda85..e2d48ea0a8 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -18,7 +18,7 @@ class PrintEventsTests extends APITests { @Test void postPrintEventsTest() { JsonObject printRequest = getPrintEvent(); - Response response = restAssuredClient.post(printRequest, printEventsUrl("/create-batch"), "post-print-event"); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_CREATED)); } @@ -26,7 +26,7 @@ void postPrintEventsTest() { void postPrintEventsWithInvalidField() { JsonObject printRequest = getPrintEvent(); printRequest.put("invalidField", "invalid"); - Response response = restAssuredClient.post(printRequest, printEventsUrl("/create-batch"), "post-print-event"); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); } @@ -35,7 +35,7 @@ void postPrintEventsWithInvalidField_EmptyRequestIdsList() { JsonObject printRequest = getPrintEvent(); List requestIds = List.of(); printRequest.put("requestIds", requestIds); - Response response = restAssuredClient.post(printRequest, printEventsUrl("/create-batch"), "post-print-event"); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); } @@ -43,7 +43,7 @@ void postPrintEventsWithInvalidField_EmptyRequestIdsList() { void postPrintEventsWithInvalidField_NullField() { JsonObject printRequest = getPrintEvent(); printRequest.put("requesterId", null); - Response response = restAssuredClient.post(printRequest, printEventsUrl("/create-batch"), "post-print-event"); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); } diff --git a/src/test/java/api/support/fakes/FakeOkapi.java b/src/test/java/api/support/fakes/FakeOkapi.java index 7c3b93fcba..1ed5b8f5b0 100644 --- a/src/test/java/api/support/fakes/FakeOkapi.java +++ b/src/test/java/api/support/fakes/FakeOkapi.java @@ -423,7 +423,7 @@ public void start(Promise startFuture) throws IOException { .create().register(router); new FakeStorageModuleBuilder() - .withRootPath("/print-events-storage/print-events/create-batch") + .withRootPath("/print-events-storage/print-events-entry") .withChangeMetadata() .create().register(router); diff --git a/src/test/java/api/support/http/InterfaceUrls.java b/src/test/java/api/support/http/InterfaceUrls.java index f85577d3a6..23c5878ecc 100644 --- a/src/test/java/api/support/http/InterfaceUrls.java +++ b/src/test/java/api/support/http/InterfaceUrls.java @@ -339,6 +339,6 @@ public static URL circulationSettingsUrl(String subPath) { } public static URL printEventsUrl(String subPath) { - return circulationModuleUrl("/circulation/print-events" + subPath); + return circulationModuleUrl("/circulation" + subPath); } } From 949689a85b9392e476052ecd4ecf3c91d41d7fc0 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Mon, 15 Jul 2024 16:17:25 +0530 Subject: [PATCH 11/38] CIRC-2099 added validations for print event flag and request --- descriptors/ModuleDescriptor-template.json | 6 +- .../resources/PrintEventsResource.java | 64 ++++++++++++++++ .../api/printEvents/PrintEventsTests.java | 76 ++++++++++++++++++- 3 files changed, 141 insertions(+), 5 deletions(-) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index d038e74136..3f260fbef6 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -745,10 +745,10 @@ "methods": ["POST"], "pathPattern": "/circulation/print-events-entry", "permissionsRequired": [ - "circulation.print-events.post" + "circulation.print-events-entry.item.post" ], "modulePermissions": [ - "circulation-storage.print-events.post" + "print-events-storage.print-events-entry.item.post" ] } ] @@ -1348,7 +1348,7 @@ ], "permissionSets": [ { - "permissionName": "circulation.print-events.post", + "permissionName": "circulation.print-events-entry.item.post", "displayName": "circulation - create print events", "description": "create print event logs" }, diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index aa10754e8f..0975a1fd36 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -5,8 +5,12 @@ import io.vertx.ext.web.RoutingContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.folio.circulation.domain.CirculationSetting; +import org.folio.circulation.domain.MultipleRecords; import org.folio.circulation.domain.PrintEventRequest; +import org.folio.circulation.infrastructure.storage.CirculationSettingsRepository; import org.folio.circulation.infrastructure.storage.PrintEventsRepository; +import org.folio.circulation.infrastructure.storage.requests.RequestRepository; import org.folio.circulation.support.Clients; import org.folio.circulation.support.RouteRegistration; import org.folio.circulation.support.http.server.JsonHttpResponse; @@ -14,14 +18,24 @@ import org.folio.circulation.support.results.Result; import java.lang.invoke.MethodHandles; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.concurrent.CompletableFuture; import java.util.function.Function; import static org.folio.circulation.support.ValidationErrorFailure.singleValidationError; +import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; import static org.folio.circulation.support.results.Result.ofAsync; import static org.folio.circulation.support.results.Result.succeeded; public class PrintEventsResource extends Resource { private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); + private static final String PRINT_EVENT_FLAG_QUERY = "query=name=Enable print event log"; + private static final String PRINT_EVENT_FEATURE_DISABLED_ERROR = "print event feature is disabled for this tenant"; + private static final String NO_CONFIG_FOUND_ERROR = "No configuration found for print event feature"; + private static final String MULTIPLE_CONFIGS_ERROR = "Multiple configurations found for print event feature"; + private static final String PRINT_EVENT_FLAG_PROPERTY_NAME = "Enable Print Event"; public PrintEventsResource(HttpClient client) { super(client); @@ -37,6 +51,8 @@ void create(RoutingContext routingContext) { final var context = new WebContext(routingContext); final var clients = Clients.create(context, client); final var printEventsRepository = new PrintEventsRepository(clients); + final var circulationSettingsRepository = new CirculationSettingsRepository(clients); + final var requestRepository = new RequestRepository(clients); final var incomingRepresentation = routingContext.body().asJsonObject(); final var printEventRequest = PrintEventRequest.from(incomingRepresentation); @@ -44,6 +60,8 @@ void create(RoutingContext routingContext) { ofAsync(printEventRequest) .thenApply(refuseWhenPrintEventRequestIsInvalid()) + .thenCompose(r -> r.after(validatePrintEventFeatureFlag(circulationSettingsRepository))) + .thenCompose(r -> r.after(validateRequests(requestRepository))) .thenCompose(r -> r.after(printEventsRepository::create)) .thenApply(r -> r.map(response -> { assert printEventRequest != null; @@ -52,9 +70,55 @@ void create(RoutingContext routingContext) { .thenAccept(context::writeResultToHttpResponse); } + private static Function>> + validateRequests(RequestRepository requestRepository) { + return printRequest -> requestRepository.fetchRequests(printRequest.getRequestIds()) + .thenApply(printRequestList -> printRequestList.map(Collection::size)).thenApply(size -> { + if (size.value() != printRequest.getRequestIds().size()) { + return Result.failed(singleValidationError("invalid request found", "", "")); + } + return succeeded(printRequest); + }); + } + private static Function, Result> refuseWhenPrintEventRequestIsInvalid() { return r -> r.failWhen(printEventRequest -> succeeded(printEventRequest == null), circulationSetting -> singleValidationError("Print Event Request JSON is invalid", "", "")); } + + private static Function>> validatePrintEventFeatureFlag( + CirculationSettingsRepository circulationSettingsRepository) { + return printEventRequest -> circulationSettingsRepository.findBy(formatString(PRINT_EVENT_FLAG_QUERY)) + .thenApply(result -> handleCirculationSettingResult(result.map(MultipleRecords::getRecords), printEventRequest)); + } + + private static Result handleCirculationSettingResult(Result> result, + PrintEventRequest printEventRequest) { + + int size = result.value().size(); + if (size == 0) { + return Result.failed(singleValidationError(NO_CONFIG_FOUND_ERROR, "", "")); + } else if (size > 1) { + return Result.failed(singleValidationError(MULTIPLE_CONFIGS_ERROR, "", "")); + } + boolean isEnabled = result.value().stream() + .map(x -> Boolean.valueOf(getProperty(x.getValue(), PRINT_EVENT_FLAG_PROPERTY_NAME))).findFirst().orElse(true); + + if (!isEnabled) { + return Result.failed(singleValidationError(PRINT_EVENT_FEATURE_DISABLED_ERROR, "", "")); + } + return succeeded(printEventRequest); + } + + public static String formatString(String input) { + String[] parts = input.split("=", 2); + if (parts.length != 2) { + return input; + } + String encodedKey = URLEncoder.encode(parts[0], StandardCharsets.UTF_8); + String encodedValue = URLEncoder.encode(parts[1], StandardCharsets.UTF_8); + return encodedKey + "=" + encodedValue.replace("+", "%20"); + } + } diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index e2d48ea0a8..691b972266 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -1,11 +1,16 @@ package api.printEvents; import api.support.APITests; +import api.support.builders.CirculationSettingBuilder; +import api.support.builders.RequestBuilder; import io.vertx.core.json.JsonObject; import org.folio.circulation.support.http.client.Response; import org.junit.jupiter.api.Test; import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import static api.support.http.InterfaceUrls.printEventsUrl; import static api.support.matchers.ResponseStatusCodeMatcher.hasStatus; @@ -15,13 +20,68 @@ class PrintEventsTests extends APITests { + @Test void postPrintEventsTest() { + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("Enable print event log") + .withValue(new JsonObject().put("Enable Print Event", true))); JsonObject printRequest = getPrintEvent(); + printRequest.put("requestIds", createOneHundredRequests()); + System.out.println(printRequest.getString("requestIds")); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_CREATED)); } + @Test + void postPrintEventsWhenCirculationSettingIsNotPresentTest() { + JsonObject printRequest = getPrintEvent(); + printRequest.put("requestIds", List.of(UUID.randomUUID())); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); + } + + @Test + void postPrintEventsWhenDuplicateCirculationSettingFound() { + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("Enable print event log") + .withValue(new JsonObject().put("Enable Print Event", true))); + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("Enable print event log") + .withValue(new JsonObject().put("Enable-Print-Event", false))); + + JsonObject printRequest = getPrintEvent(); + printRequest.put("requestIds", List.of(UUID.randomUUID())); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); + } + + @Test + void postPrintEventsWhenPrintEventSettingIsDisable() { + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("Enable print event log") + .withValue(new JsonObject().put("Enable Print Event", false))); + + JsonObject printRequest = getPrintEvent(); + printRequest.put("requestIds", List.of(UUID.randomUUID())); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); + } + + @Test + void postPrintEventsWithInvalidRequestId() { + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("Enable print event log") + .withValue(new JsonObject().put("Enable Print Event", true))); + JsonObject printRequest = getPrintEvent(); + List RequestIds = createOneHundredRequests(); + RequestIds.add(UUID.randomUUID()); + printRequest.put("requestIds", RequestIds); + Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); + } + + @Test void postPrintEventsWithInvalidField() { JsonObject printRequest = getPrintEvent(); @@ -48,11 +108,23 @@ void postPrintEventsWithInvalidField_NullField() { } private JsonObject getPrintEvent() { - List requestIds = List.of("5f5751b4-e352-4121-adca-204b0c2aec43", "5f5751b4-e352-4121-adca-204b0c2aec44"); return new JsonObject() - .put("requestIds", requestIds) .put("requesterId", "5f5751b4-e352-4121-adca-204b0c2aec43") .put("requesterName", "requester") .put("printEventDate", "2024-06-25T14:30:00Z"); } + + private List createOneHundredRequests() { + final UUID pickupServicePointId = servicePointsFixture.cd1().getId(); + + return IntStream.range(0, 100).mapToObj(notUsed -> requestsFixture.place( + new RequestBuilder() + .open() + .page() + .forItem(itemsFixture.basedUponSmallAngryPlanet()) + .by(usersFixture.charlotte()) + .fulfillToHoldShelf() + .withPickupServicePointId(pickupServicePointId)).getId()) + .collect(Collectors.toList()); + } } From a11ae9945229ed93fdbaec49ca358a404286f135 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Tue, 16 Jul 2024 19:18:48 +0530 Subject: [PATCH 12/38] CIRC-2099 added loggers --- .../org/folio/circulation/domain/CirculationSetting.java | 1 + .../storage/CirculationSettingsRepository.java | 9 +++++++-- .../folio/circulation/resources/PrintEventsResource.java | 6 +++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/CirculationSetting.java b/src/main/java/org/folio/circulation/domain/CirculationSetting.java index 03f254f1ed..4f5c67342c 100644 --- a/src/main/java/org/folio/circulation/domain/CirculationSetting.java +++ b/src/main/java/org/folio/circulation/domain/CirculationSetting.java @@ -39,6 +39,7 @@ public class CirculationSetting { private final JsonObject value; public static CirculationSetting from(JsonObject representation) { + log.info("from {}", representation); final var id = getProperty(representation, ID_FIELD); final var name = getProperty(representation, NAME_FIELD); final var value = getObjectProperty(representation, VALUE_FIELD); diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java index 8125f1761b..809c71adb2 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java @@ -40,8 +40,13 @@ public CompletableFuture> getById(String id) { public CompletableFuture>> findBy(String query) { return circulationSettingsStorageClient.getManyWithRawQueryStringParameters(query) - .thenApply(flatMapResult(response -> - MultipleRecords.from(response, CirculationSetting::from, RECORDS_PROPERTY_NAME))); + .thenApply(flatMapResult(response -> { + log.info("************* {}", response); + log.info(MultipleRecords.from(response, CirculationSetting::from, RECORDS_PROPERTY_NAME).value().getRecords()); + return MultipleRecords.from(response, CirculationSetting::from, RECORDS_PROPERTY_NAME); + } + )); + } public CompletableFuture> create( diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index 0975a1fd36..e4b78916ec 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -90,7 +90,11 @@ void create(RoutingContext routingContext) { private static Function>> validatePrintEventFeatureFlag( CirculationSettingsRepository circulationSettingsRepository) { return printEventRequest -> circulationSettingsRepository.findBy(formatString(PRINT_EVENT_FLAG_QUERY)) - .thenApply(result -> handleCirculationSettingResult(result.map(MultipleRecords::getRecords), printEventRequest)); + .thenApply(result -> { + log.info("validatePrintEventFeatureFlag:: result value {}", result.value()); + log.info("validatePrintEventFeatureFlag:: result value {}", result.value().getRecords()); + return handleCirculationSettingResult(result.map(MultipleRecords::getRecords), printEventRequest); + }); } private static Result handleCirculationSettingResult(Result> result, From 2e7c959e90c90de620056e10760c622617ca78fd Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Wed, 17 Jul 2024 14:03:24 +0530 Subject: [PATCH 13/38] CIRC-2099 added circulation setting module permission --- descriptors/ModuleDescriptor-template.json | 3 ++- src/test/java/api/printEvents/PrintEventsTests.java | 10 ++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 3f260fbef6..4223f70edf 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -748,7 +748,8 @@ "circulation.print-events-entry.item.post" ], "modulePermissions": [ - "print-events-storage.print-events-entry.item.post" + "print-events-storage.print-events-entry.item.post", + "circulation-storage.circulation-settings.collection.get" ] } ] diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index 691b972266..5ba3e6b859 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; import java.util.stream.IntStream; import static api.support.http.InterfaceUrls.printEventsUrl; @@ -74,9 +73,9 @@ void postPrintEventsWithInvalidRequestId() { .withName("Enable print event log") .withValue(new JsonObject().put("Enable Print Event", true))); JsonObject printRequest = getPrintEvent(); - List RequestIds = createOneHundredRequests(); - RequestIds.add(UUID.randomUUID()); - printRequest.put("requestIds", RequestIds); + List requestIds = createOneHundredRequests(); + requestIds.add(UUID.randomUUID()); + printRequest.put("requestIds", requestIds); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); } @@ -124,7 +123,6 @@ private List createOneHundredRequests() { .forItem(itemsFixture.basedUponSmallAngryPlanet()) .by(usersFixture.charlotte()) .fulfillToHoldShelf() - .withPickupServicePointId(pickupServicePointId)).getId()) - .collect(Collectors.toList()); + .withPickupServicePointId(pickupServicePointId)).getId()).toList(); } } From bf22a755ca1613440618846bf8b8e5e1600be0f0 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Thu, 18 Jul 2024 11:00:28 +0530 Subject: [PATCH 14/38] CIRC-2099 changed circulation setting name and flag name in request --- .../resources/PrintEventsResource.java | 24 +++---------- .../api/printEvents/PrintEventsTests.java | 35 ++++++++++--------- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index e4b78916ec..57a69fd9cf 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -18,8 +18,6 @@ import org.folio.circulation.support.results.Result; import java.lang.invoke.MethodHandles; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -31,11 +29,11 @@ public class PrintEventsResource extends Resource { private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - private static final String PRINT_EVENT_FLAG_QUERY = "query=name=Enable print event log"; + private static final String PRINT_EVENT_FLAG_QUERY = "query=name=printEventLogFeature"; private static final String PRINT_EVENT_FEATURE_DISABLED_ERROR = "print event feature is disabled for this tenant"; private static final String NO_CONFIG_FOUND_ERROR = "No configuration found for print event feature"; private static final String MULTIPLE_CONFIGS_ERROR = "Multiple configurations found for print event feature"; - private static final String PRINT_EVENT_FLAG_PROPERTY_NAME = "Enable Print Event"; + private static final String PRINT_EVENT_FLAG_PROPERTY_NAME = "enablePrintLog"; public PrintEventsResource(HttpClient client) { super(client); @@ -63,10 +61,7 @@ void create(RoutingContext routingContext) { .thenCompose(r -> r.after(validatePrintEventFeatureFlag(circulationSettingsRepository))) .thenCompose(r -> r.after(validateRequests(requestRepository))) .thenCompose(r -> r.after(printEventsRepository::create)) - .thenApply(r -> r.map(response -> { - assert printEventRequest != null; - return JsonHttpResponse.created(printEventRequest.getRepresentation(), null); - })) + .thenApply(r -> r.map(response -> JsonHttpResponse.created(null, null))) .thenAccept(context::writeResultToHttpResponse); } @@ -89,9 +84,8 @@ void create(RoutingContext routingContext) { private static Function>> validatePrintEventFeatureFlag( CirculationSettingsRepository circulationSettingsRepository) { - return printEventRequest -> circulationSettingsRepository.findBy(formatString(PRINT_EVENT_FLAG_QUERY)) + return printEventRequest -> circulationSettingsRepository.findBy(PRINT_EVENT_FLAG_QUERY) .thenApply(result -> { - log.info("validatePrintEventFeatureFlag:: result value {}", result.value()); log.info("validatePrintEventFeatureFlag:: result value {}", result.value().getRecords()); return handleCirculationSettingResult(result.map(MultipleRecords::getRecords), printEventRequest); }); @@ -115,14 +109,4 @@ private static Result handleCirculationSettingResult(Result requestIds = createOneHundredRequests(); + List requestIds = new ArrayList<>(createOneHundredRequests()); requestIds.add(UUID.randomUUID()); printRequest.put("requestIds", requestIds); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); @@ -117,12 +118,12 @@ private List createOneHundredRequests() { final UUID pickupServicePointId = servicePointsFixture.cd1().getId(); return IntStream.range(0, 100).mapToObj(notUsed -> requestsFixture.place( - new RequestBuilder() - .open() - .page() - .forItem(itemsFixture.basedUponSmallAngryPlanet()) - .by(usersFixture.charlotte()) - .fulfillToHoldShelf() - .withPickupServicePointId(pickupServicePointId)).getId()).toList(); + new RequestBuilder() + .open() + .page() + .forItem(itemsFixture.basedUponSmallAngryPlanet()) + .by(usersFixture.charlotte()) + .fulfillToHoldShelf() + .withPickupServicePointId(pickupServicePointId)).getId()).toList(); } } From 5c9ea507f19e09c842e30ac6c4321baeec8319bc Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 13:13:34 +0530 Subject: [PATCH 15/38] CIRC-2100 Fetching print event details for request when request is fetched by CQL query --- descriptors/ModuleDescriptor-template.json | 3 +- .../circulation/domain/PrintEventDetail.java | 45 ++++++++++++++ .../org/folio/circulation/domain/Request.java | 8 ++- .../domain/RequestRepresentation.java | 21 +++++++ .../storage/PrintEventsRepository.java | 60 ++++++++++++++++++- .../storage/requests/RequestRepository.java | 17 ++++-- .../storage/users/UserRepository.java | 14 ++++- .../folio/circulation/support/Clients.java | 15 ++++- 8 files changed, 170 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/folio/circulation/domain/PrintEventDetail.java diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 4223f70edf..ce90a5c4e0 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -2065,7 +2065,8 @@ "users.collection.get", "addresstypes.collection.get", "usergroups.collection.get", - "usergroups.item.get" + "usergroups.item.get", + "print-events-storage.print-events-status.item.post" ], "visible": false }, diff --git a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java new file mode 100644 index 0000000000..6ae9e2459f --- /dev/null +++ b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java @@ -0,0 +1,45 @@ +package org.folio.circulation.domain; + +import io.vertx.core.json.JsonObject; +import lombok.AllArgsConstructor; +import lombok.With; + +import java.time.ZonedDateTime; + +import static org.folio.circulation.support.json.JsonPropertyFetcher.getDateTimeProperty; +import static org.folio.circulation.support.json.JsonPropertyFetcher.getIntegerProperty; +import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; + + +@AllArgsConstructor +public class PrintEventDetail { + + private final JsonObject representation; + @With + private final User printeduser; + + public static PrintEventDetail from(JsonObject representation) { + return new PrintEventDetail(representation, null); + } + + public String getUserId() { + return getProperty(representation, "userId"); + } + + public String getRequestId() { + return getProperty(representation, "requestId"); + } + + public int getCount() { + return getIntegerProperty(representation, "count", 0); + } + + public ZonedDateTime getPrintEventDate() { + return getDateTimeProperty(representation, "printEventDate"); + } + + public User getUser() { + return printeduser; + } + +} diff --git a/src/main/java/org/folio/circulation/domain/Request.java b/src/main/java/org/folio/circulation/domain/Request.java index 0774075a5b..d1cecb8085 100644 --- a/src/main/java/org/folio/circulation/domain/Request.java +++ b/src/main/java/org/folio/circulation/domain/Request.java @@ -102,13 +102,15 @@ public class Request implements ItemRelatedRecord, UserRelatedRecord { private boolean changedPosition; private Integer previousPosition; private boolean changedStatus; + @With + private PrintEventDetail printEventDetail; public static Request from(JsonObject representation) { // TODO: make sure that operation and TLR settings don't matter for all processes calling // this constructor return new Request(null, null, representation, null, null, new ArrayList<>(), new HashMap<>(), null, null, null, null, null, null, false, null, - false); + false, null); } public static Request from(TlrSettingsConfiguration tlrSettingsConfiguration, Operation operation, @@ -116,7 +118,7 @@ public static Request from(TlrSettingsConfiguration tlrSettingsConfiguration, Op return new Request(tlrSettingsConfiguration, operation, representation, null, null, new ArrayList<>(), new HashMap<>(), null, null, null, null, null, null, false, - null, false); + null, false, null); } public JsonObject asJson() { @@ -223,7 +225,7 @@ public Request withItem(Item newItem) { cancellationReasonRepresentation, instance, instanceItems, instanceItemsRequestPolicies, newItem, requester, proxy, addressType, loan == null ? null : loan.withItem(newItem), pickupServicePoint, changedPosition, - previousPosition, changedStatus); + previousPosition, changedStatus, printEventDetail); } @Override diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index f7bb0af944..67802769e6 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -33,6 +33,7 @@ public JsonObject extendedRepresentation(Request request) { addAdditionalProxyProperties(requestRepresentation, request.getProxy()); addAdditionalServicePointProperties(requestRepresentation, request.getPickupServicePoint()); addDeliveryAddress(requestRepresentation, request, request.getRequester()); + addPrintEventProperties(requestRepresentation, request.getPrintEventDetail()); removeSearchIndexFields(requestRepresentation); @@ -258,5 +259,25 @@ private static JsonObject userSummary(User user) { private static void removeSearchIndexFields(JsonObject request) { request.remove("searchIndex"); } + + private static void addPrintEventProperties(JsonObject request, PrintEventDetail printEventDetail) { + if (printEventDetail == null) { + log.info("addPrintEventProperties:: printEvent property is null for requestId {}", request.getString("id")); + return; + } + var printEvent = new JsonObject(); + printEvent.put("count", printEventDetail.getCount()); + printEvent.put("lastPrintedDate", printEventDetail.getPrintEventDate()); + + var userSummary = new JsonObject(); + var user = printEventDetail.getUser(); + + write(userSummary, "lastName", user.getLastName()); + write(userSummary, "firstName", user.getFirstName()); + write(userSummary, "middleName", user.getMiddleName()); + + printEvent.put("lastPrintRequester", userSummary); + } + } diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index 1a179857ff..385c19ebae 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -1,26 +1,41 @@ package org.folio.circulation.infrastructure.storage; +import io.vertx.core.json.JsonObject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.folio.circulation.domain.MultipleRecords; +import org.folio.circulation.domain.PrintEventDetail; import org.folio.circulation.domain.PrintEventRequest; +import org.folio.circulation.domain.Request; import org.folio.circulation.support.Clients; import org.folio.circulation.support.CollectionResourceClient; import org.folio.circulation.support.http.client.ResponseInterpreter; import org.folio.circulation.support.results.Result; import java.lang.invoke.MethodHandles; +import java.util.Collection; +import java.util.Map; import java.util.concurrent.CompletableFuture; +import static java.util.concurrent.CompletableFuture.completedFuture; import static org.folio.circulation.support.http.ResponseMapping.forwardOnFailure; +import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; +import static org.folio.circulation.support.results.Result.of; import static org.folio.circulation.support.results.Result.succeeded; +import static org.folio.circulation.support.results.ResultBinding.flatMapResult; +import static org.folio.circulation.support.utils.LogUtil.multipleRecordsAsString; public class PrintEventsRepository { private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); private final CollectionResourceClient printEventsStorageClient; + private final CollectionResourceClient printEventsStorageStatusClient; + private final CirculationSettingsRepository circulationSettingsRepository; public PrintEventsRepository(Clients clients) { - printEventsStorageClient = clients.printEventsStorageClient(); + this.printEventsStorageClient = clients.printEventsStorageClient(); + this.printEventsStorageStatusClient = clients.printEventsStorageStatusClient(); + this.circulationSettingsRepository = new CirculationSettingsRepository(clients); } public CompletableFuture> create(PrintEventRequest printEventRequest) { @@ -32,4 +47,47 @@ public CompletableFuture> create(PrintEventRequest printEventReques return printEventsStorageClient.post(storagePrintEventRequest).thenApply(interpreter::flatMap); } + public CompletableFuture>> findPrintEventDetails( + MultipleRecords multipleRequests) { + log.debug("findPrintEventDetails:: parameters multipleRequests: {}", + () -> multipleRecordsAsString(multipleRequests)); + return validatePrintEventFeatureFlag() + .thenCompose(isEnabled -> isEnabled ? fetchAndMapPrintEventDetails(multipleRequests) + : completedFuture(succeeded(multipleRequests))); + } + + private CompletableFuture>> fetchAndMapPrintEventDetails( + MultipleRecords multipleRequests) { + var requestIds = multipleRequests.toKeys(Request::getId); + return fetchPrintDetailsByRequestIds(requestIds) + .thenApply(printEventRecordsResult -> printEventRecordsResult + .next(printEventRecords -> mapPrintEventDetailsToRequest(printEventRecords, multipleRequests))); + } + + private CompletableFuture validatePrintEventFeatureFlag() { + return circulationSettingsRepository.findBy("query=name=printEventLogFeature") + .thenApply(res -> res.value().getRecords() + .stream() + .map(setting -> Boolean.valueOf(getProperty(setting.getValue(), "enablePrintLog"))) + .findFirst() + .orElse(false)); + } + + private CompletableFuture>> fetchPrintDetailsByRequestIds + (Collection requestIds) { + log.debug("fetchPrintDetailsByRequestIds:: fetching print event details for requestIds {}", requestIds); + return printEventsStorageStatusClient.post(new JsonObject().put("requestIds", requestIds)) + .thenApply(flatMapResult(response -> + MultipleRecords.from(response, PrintEventDetail::from, "printEventsStatusResponses"))); + } + + private Result> mapPrintEventDetailsToRequest( + MultipleRecords printEventDetails, MultipleRecords requests) { + log.debug("mapPrintEventDetailsToRequest:: Mapping print event details {} with requests {}", + () -> multipleRecordsAsString(printEventDetails), () -> multipleRecordsAsString(requests)); + Map printEventDetailMap = printEventDetails.toMap(PrintEventDetail::getRequestId); + return of(() -> requests.mapRecords(request -> + request.withPrintEventDetail(printEventDetailMap.getOrDefault(request.getId(), null)))); + } + } diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java index 208c2bf0da..750b904252 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java @@ -30,6 +30,7 @@ import org.folio.circulation.domain.ServicePoint; import org.folio.circulation.domain.StoredRequestRepresentation; import org.folio.circulation.domain.User; +import org.folio.circulation.infrastructure.storage.PrintEventsRepository; import org.folio.circulation.infrastructure.storage.ServicePointRepository; import org.folio.circulation.infrastructure.storage.inventory.InstanceRepository; import org.folio.circulation.infrastructure.storage.inventory.ItemRepository; @@ -66,6 +67,7 @@ public class RequestRepository { private final ServicePointRepository servicePointRepository; private final PatronGroupRepository patronGroupRepository; private final InstanceRepository instanceRepository; + private final PrintEventsRepository printEventsRepository; /** * Public constructor to avoid creating repositories twice @@ -76,7 +78,8 @@ public RequestRepository(org.folio.circulation.support.Clients clients, this(new Clients(clients.requestsStorage(), clients.requestsBatchStorage(), clients.cancellationReasonStorage()), itemRepository, userRepository, - loanRepository, servicePointRepository, patronGroupRepository, new InstanceRepository(clients)); + loanRepository, servicePointRepository, patronGroupRepository, new InstanceRepository(clients), + new PrintEventsRepository(clients)); } /** @@ -87,9 +90,10 @@ public RequestRepository(org.folio.circulation.support.Clients clients) { } private RequestRepository(Clients clients, ItemRepository itemRepository, - UserRepository userRepository, LoanRepository loanRepository, - ServicePointRepository servicePointRepository, - PatronGroupRepository patronGroupRepository, InstanceRepository instanceRepository) { + UserRepository userRepository, LoanRepository loanRepository, + ServicePointRepository servicePointRepository, + PatronGroupRepository patronGroupRepository, InstanceRepository instanceRepository, + PrintEventsRepository printEventsRepository) { this.requestsStorageClient = clients.getRequestsStorageClient(); this.requestsBatchStorageClient = clients.getRequestsBatchStorageClient(); @@ -100,6 +104,7 @@ private RequestRepository(Clients clients, ItemRepository itemRepository, this.servicePointRepository = servicePointRepository; this.patronGroupRepository = patronGroupRepository; this.instanceRepository = instanceRepository; + this.printEventsRepository = printEventsRepository; } public static RequestRepository using( @@ -113,7 +118,8 @@ public static RequestRepository using( itemRepository, userRepository, loanRepository, new ServicePointRepository(clients), new PatronGroupRepository(clients), - new InstanceRepository(clients)); + new InstanceRepository(clients), + new PrintEventsRepository(clients)); } public CompletableFuture>> findBy(String query) { @@ -135,6 +141,7 @@ private CompletableFuture>> fetchAdditionalField return ofAsync(() -> requestRecords) .thenComposeAsync(requests -> itemRepository.fetchItemsFor(requests, Request::withItem)) + .thenComposeAsync(result -> result.after(printEventsRepository::findPrintEventDetails)) .thenComposeAsync(result -> result.after(loanRepository::findOpenLoansFor)) .thenComposeAsync(result -> result.after(servicePointRepository::findServicePointsForRequests)) .thenComposeAsync(result -> result.after(userRepository::findUsersForRequests)) diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java index f7ba66c68a..8e8256f990 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java @@ -23,6 +23,7 @@ import java.util.stream.Collectors; import org.folio.circulation.domain.Loan; import org.folio.circulation.domain.MultipleRecords; +import org.folio.circulation.domain.PrintEventDetail; import org.folio.circulation.domain.Request; import org.folio.circulation.domain.User; import org.folio.circulation.domain.UserRelatedRecord; @@ -271,6 +272,10 @@ private ArrayList getUsersFromRequest(Request request) { usersToFetch.add(request.getProxyUserId()); } + if (request.getPrintEventDetail() != null && request.getPrintEventDetail().getUserId() != null) { + usersToFetch.add(request.getPrintEventDetail().getUserId()); + } + return usersToFetch; } @@ -282,7 +287,14 @@ private Request matchUsersToRequests( return request .withRequester(userMap.getOrDefault(request.getUserId(), null)) - .withProxy(userMap.getOrDefault(request.getProxyUserId(), null)); + .withProxy(userMap.getOrDefault(request.getProxyUserId(), null)) + .withPrintEventDetail(mapUserToPrintEventDetails(request, userMap)); + } + + private PrintEventDetail mapUserToPrintEventDetails(Request request, Map userMap) { + var printEventDetail = request.getPrintEventDetail(); + return printEventDetail != null ? + printEventDetail.withPrinteduser(userMap.getOrDefault(printEventDetail.getUserId(), null)) : null; } private Result> mapResponseToUsers(Response response) { diff --git a/src/main/java/org/folio/circulation/support/Clients.java b/src/main/java/org/folio/circulation/support/Clients.java index 99be88183c..9ff7028965 100644 --- a/src/main/java/org/folio/circulation/support/Clients.java +++ b/src/main/java/org/folio/circulation/support/Clients.java @@ -71,7 +71,7 @@ public class Clients { private final GetManyRecordsClient settingsStorageClient; private final CollectionResourceClient circulationSettingsStorageClient; private final CollectionResourceClient printEventsStorageClient; - + private final CollectionResourceClient printEventsStorageStatusClient; public static Clients create(WebContext context, HttpClient httpClient) { return new Clients(context.createHttpClient(httpClient), context); @@ -141,7 +141,7 @@ private Clients(OkapiHttpClient client, WebContext context) { circulationItemClient = createCirculationItemClient(client, context); circulationSettingsStorageClient = createCirculationSettingsStorageClient(client, context); printEventsStorageClient = createPrintEventsStorageClient(client, context); - + printEventsStorageStatusClient = createPrintEventsStorageStatusClient(client, context); } catch(MalformedURLException e) { throw new InvalidOkapiLocationException(context.getOkapiLocation(), e); @@ -388,6 +388,10 @@ public CollectionResourceClient printEventsStorageClient() { return printEventsStorageClient; } + public CollectionResourceClient printEventsStorageStatusClient() { + return printEventsStorageStatusClient; + } + private static CollectionResourceClient getCollectionResourceClient( OkapiHttpClient client, WebContext context, String path) @@ -829,6 +833,13 @@ private CollectionResourceClient createPrintEventsStorageClient( "/print-events-storage/print-events-entry"); } + private CollectionResourceClient createPrintEventsStorageStatusClient( + OkapiHttpClient client, WebContext context) throws MalformedURLException { + + return getCollectionResourceClient(client, context, + "/print-events-storage/print-events-status"); + } + private GetManyRecordsClient createSettingsStorageClient( OkapiHttpClient client, WebContext context) throws MalformedURLException { From 2dd1fe43f65d770d59b59332ecc980ae189cca97 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 13:20:25 +0530 Subject: [PATCH 16/38] CIRC-2100 Fixing build issue --- .../java/org/folio/circulation/domain/RequestQueueTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/folio/circulation/domain/RequestQueueTests.java b/src/test/java/org/folio/circulation/domain/RequestQueueTests.java index 345472b75e..b6c02f33df 100644 --- a/src/test/java/org/folio/circulation/domain/RequestQueueTests.java +++ b/src/test/java/org/folio/circulation/domain/RequestQueueTests.java @@ -102,7 +102,7 @@ private static Request buildRequest(int position, RequestStatus status, String r .put("position", position); return new Request(null, null, json, null, null, null, null, null, null, null, null, null, - null, false, null, false); + null, false, null, false, null); } private static String randomId() { From 8bf803ca2116c5a9e5612bec84319a9884ae2446 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 17:06:26 +0530 Subject: [PATCH 17/38] CIRC-2100 Adding loggers --- .../storage/PrintEventsRepository.java | 12 ++++++++---- .../infrastructure/storage/users/UserRepository.java | 5 +++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index 385c19ebae..360dcc332b 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -59,9 +59,13 @@ public CompletableFuture>> findPrintEventDetails private CompletableFuture>> fetchAndMapPrintEventDetails( MultipleRecords multipleRequests) { var requestIds = multipleRequests.toKeys(Request::getId); + log.info("fetchAndMapPrintEventDetails:: requestIds {}", requestIds); return fetchPrintDetailsByRequestIds(requestIds) - .thenApply(printEventRecordsResult -> printEventRecordsResult - .next(printEventRecords -> mapPrintEventDetailsToRequest(printEventRecords, multipleRequests))); + .thenApply(printEventRecordsResult -> { + log.info("printEventRecordsResult"); + return printEventRecordsResult + .next(printEventRecords -> mapPrintEventDetailsToRequest(printEventRecords, multipleRequests)); + }); } private CompletableFuture validatePrintEventFeatureFlag() { @@ -75,7 +79,7 @@ private CompletableFuture validatePrintEventFeatureFlag() { private CompletableFuture>> fetchPrintDetailsByRequestIds (Collection requestIds) { - log.debug("fetchPrintDetailsByRequestIds:: fetching print event details for requestIds {}", requestIds); + log.info("fetchPrintDetailsByRequestIds:: fetching print event details for requestIds {}", requestIds); return printEventsStorageStatusClient.post(new JsonObject().put("requestIds", requestIds)) .thenApply(flatMapResult(response -> MultipleRecords.from(response, PrintEventDetail::from, "printEventsStatusResponses"))); @@ -83,7 +87,7 @@ private CompletableFuture validatePrintEventFeatureFlag() { private Result> mapPrintEventDetailsToRequest( MultipleRecords printEventDetails, MultipleRecords requests) { - log.debug("mapPrintEventDetailsToRequest:: Mapping print event details {} with requests {}", + log.info("mapPrintEventDetailsToRequest:: Mapping print event details {} with requests {}", () -> multipleRecordsAsString(printEventDetails), () -> multipleRecordsAsString(requests)); Map printEventDetailMap = printEventDetails.toMap(PrintEventDetail::getRequestId); return of(() -> requests.mapRecords(request -> diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java index 8e8256f990..3848bf1117 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java @@ -292,7 +292,12 @@ private Request matchUsersToRequests( } private PrintEventDetail mapUserToPrintEventDetails(Request request, Map userMap) { + log.info("mapUserToPrintEventDetails :: request {} , userMap {}", request, userMap); + log.info("mapUserToPrintEventDetails :: printEvent {}", request.getPrintEventDetail()); var printEventDetail = request.getPrintEventDetail(); + if (printEventDetail != null) + log.info(userMap.getOrDefault(printEventDetail.getUserId(),null)); + return printEventDetail != null ? printEventDetail.withPrinteduser(userMap.getOrDefault(printEventDetail.getUserId(), null)) : null; } From 9ab47243d35f5d599cc566eb723e1ec9d8e938fa Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 17:32:12 +0530 Subject: [PATCH 18/38] CIRC-2100 Adding loggers --- .../org/folio/circulation/domain/PrintEventDetail.java | 6 +++++- .../infrastructure/storage/PrintEventsRepository.java | 10 ++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java index 6ae9e2459f..8b02df1847 100644 --- a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java +++ b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java @@ -2,7 +2,9 @@ import io.vertx.core.json.JsonObject; import lombok.AllArgsConstructor; +import lombok.ToString; import lombok.With; +import lombok.extern.log4j.Log4j2; import java.time.ZonedDateTime; @@ -12,13 +14,15 @@ @AllArgsConstructor +@Log4j2 public class PrintEventDetail { - + @ToString.Include private final JsonObject representation; @With private final User printeduser; public static PrintEventDetail from(JsonObject representation) { + log.info("printEventDetail representation {}", representation); return new PrintEventDetail(representation, null); } diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index 360dcc332b..f7f382c378 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -62,7 +62,7 @@ private CompletableFuture>> fetchAndMapPrintEven log.info("fetchAndMapPrintEventDetails:: requestIds {}", requestIds); return fetchPrintDetailsByRequestIds(requestIds) .thenApply(printEventRecordsResult -> { - log.info("printEventRecordsResult"); + log.info("printEventRecordsResult {}", printEventRecordsResult); return printEventRecordsResult .next(printEventRecords -> mapPrintEventDetailsToRequest(printEventRecords, multipleRequests)); }); @@ -88,10 +88,12 @@ private CompletableFuture validatePrintEventFeatureFlag() { private Result> mapPrintEventDetailsToRequest( MultipleRecords printEventDetails, MultipleRecords requests) { log.info("mapPrintEventDetailsToRequest:: Mapping print event details {} with requests {}", - () -> multipleRecordsAsString(printEventDetails), () -> multipleRecordsAsString(requests)); + printEventDetails::getRecords, () -> multipleRecordsAsString(requests)); Map printEventDetailMap = printEventDetails.toMap(PrintEventDetail::getRequestId); - return of(() -> requests.mapRecords(request -> - request.withPrintEventDetail(printEventDetailMap.getOrDefault(request.getId(), null)))); + return of(() -> requests.mapRecords(request -> { + log.info("printEventDetailMap {}", printEventDetailMap.getOrDefault(request.getId(), null)); + return request.withPrintEventDetail(printEventDetailMap.getOrDefault(request.getId(), null)); + })); } } From 1c975f3b21c68e7c349a3c6aa727668f4905e19d Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 17:56:58 +0530 Subject: [PATCH 19/38] CIRC-2100 Changing property name --- .../java/org/folio/circulation/domain/PrintEventDetail.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java index 8b02df1847..b52a440c30 100644 --- a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java +++ b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java @@ -22,12 +22,11 @@ public class PrintEventDetail { private final User printeduser; public static PrintEventDetail from(JsonObject representation) { - log.info("printEventDetail representation {}", representation); return new PrintEventDetail(representation, null); } public String getUserId() { - return getProperty(representation, "userId"); + return getProperty(representation, "requesterId"); } public String getRequestId() { From 8766a5f98756a1a4abc928535012468b9c360f4c Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 18:41:58 +0530 Subject: [PATCH 20/38] CIRC-2100 Code Refactoring --- .../domain/RequestRepresentation.java | 15 +++++++++------ .../storage/PrintEventsRepository.java | 17 +++++------------ .../storage/users/UserRepository.java | 5 ----- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index 67802769e6..3c56392266 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -265,18 +265,21 @@ private static void addPrintEventProperties(JsonObject request, PrintEventDetail log.info("addPrintEventProperties:: printEvent property is null for requestId {}", request.getString("id")); return; } + var printEvent = new JsonObject(); printEvent.put("count", printEventDetail.getCount()); printEvent.put("lastPrintedDate", printEventDetail.getPrintEventDate()); - var userSummary = new JsonObject(); var user = printEventDetail.getUser(); + if (user != null) { + var userSummary = new JsonObject(); + write(userSummary, "lastName", user.getLastName()); + write(userSummary, "firstName", user.getFirstName()); + write(userSummary, "middleName", user.getMiddleName()); + printEvent.put("lastPrintRequester", userSummary); + } - write(userSummary, "lastName", user.getLastName()); - write(userSummary, "firstName", user.getFirstName()); - write(userSummary, "middleName", user.getMiddleName()); - - printEvent.put("lastPrintRequester", userSummary); + request.put("printDetails", printEvent); } } diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index f7f382c378..714f5b576e 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -59,13 +59,9 @@ public CompletableFuture>> findPrintEventDetails private CompletableFuture>> fetchAndMapPrintEventDetails( MultipleRecords multipleRequests) { var requestIds = multipleRequests.toKeys(Request::getId); - log.info("fetchAndMapPrintEventDetails:: requestIds {}", requestIds); return fetchPrintDetailsByRequestIds(requestIds) - .thenApply(printEventRecordsResult -> { - log.info("printEventRecordsResult {}", printEventRecordsResult); - return printEventRecordsResult - .next(printEventRecords -> mapPrintEventDetailsToRequest(printEventRecords, multipleRequests)); - }); + .thenApply(printEventRecordsResult -> printEventRecordsResult + .next(printEventRecords -> mapPrintEventDetailsToRequest(printEventRecords, multipleRequests))); } private CompletableFuture validatePrintEventFeatureFlag() { @@ -79,7 +75,7 @@ private CompletableFuture validatePrintEventFeatureFlag() { private CompletableFuture>> fetchPrintDetailsByRequestIds (Collection requestIds) { - log.info("fetchPrintDetailsByRequestIds:: fetching print event details for requestIds {}", requestIds); + log.debug("fetchPrintDetailsByRequestIds:: fetching print event details for requestIds {}", requestIds); return printEventsStorageStatusClient.post(new JsonObject().put("requestIds", requestIds)) .thenApply(flatMapResult(response -> MultipleRecords.from(response, PrintEventDetail::from, "printEventsStatusResponses"))); @@ -88,12 +84,9 @@ private CompletableFuture validatePrintEventFeatureFlag() { private Result> mapPrintEventDetailsToRequest( MultipleRecords printEventDetails, MultipleRecords requests) { log.info("mapPrintEventDetailsToRequest:: Mapping print event details {} with requests {}", - printEventDetails::getRecords, () -> multipleRecordsAsString(requests)); + () -> multipleRecordsAsString(printEventDetails), () -> multipleRecordsAsString(requests)); Map printEventDetailMap = printEventDetails.toMap(PrintEventDetail::getRequestId); - return of(() -> requests.mapRecords(request -> { - log.info("printEventDetailMap {}", printEventDetailMap.getOrDefault(request.getId(), null)); - return request.withPrintEventDetail(printEventDetailMap.getOrDefault(request.getId(), null)); - })); + return of(() -> requests.mapRecords(request -> request.withPrintEventDetail(printEventDetailMap.getOrDefault(request.getId(), null)))); } } diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java index 3848bf1117..8e8256f990 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java @@ -292,12 +292,7 @@ private Request matchUsersToRequests( } private PrintEventDetail mapUserToPrintEventDetails(Request request, Map userMap) { - log.info("mapUserToPrintEventDetails :: request {} , userMap {}", request, userMap); - log.info("mapUserToPrintEventDetails :: printEvent {}", request.getPrintEventDetail()); var printEventDetail = request.getPrintEventDetail(); - if (printEventDetail != null) - log.info(userMap.getOrDefault(printEventDetail.getUserId(),null)); - return printEventDetail != null ? printEventDetail.withPrinteduser(userMap.getOrDefault(printEventDetail.getUserId(), null)) : null; } From 8e49b2b429632cbcc7d3c73a3985a440ae4abc8d Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 19:42:55 +0530 Subject: [PATCH 21/38] CIRC-2100 Adding logs --- .../java/org/folio/circulation/domain/MultipleRecords.java | 4 +++- .../org/folio/circulation/domain/RequestRepresentation.java | 2 +- .../circulation/support/http/server/JsonHttpResponse.java | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/MultipleRecords.java b/src/main/java/org/folio/circulation/domain/MultipleRecords.java index 43cf488288..e43d2a425d 100644 --- a/src/main/java/org/folio/circulation/domain/MultipleRecords.java +++ b/src/main/java/org/folio/circulation/domain/MultipleRecords.java @@ -158,7 +158,9 @@ public JsonObject asJson(Function mapper, String recordsPropertyN final List mappedRecords = getRecords().stream() .map(mapper) .collect(Collectors.toList()); - + log.info("asJson:: jsonObject {}", new JsonObject() + .put(recordsPropertyName, new JsonArray(mappedRecords)) + .put(TOTAL_RECORDS_PROPERTY_NAME, totalRecords)); return new JsonObject() .put(recordsPropertyName, new JsonArray(mappedRecords)) .put(TOTAL_RECORDS_PROPERTY_NAME, totalRecords); diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index 3c56392266..64c25db272 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -36,7 +36,7 @@ public JsonObject extendedRepresentation(Request request) { addPrintEventProperties(requestRepresentation, request.getPrintEventDetail()); removeSearchIndexFields(requestRepresentation); - + log.info("extendedRepresentation :: {}", requestRepresentation); return requestRepresentation; } diff --git a/src/main/java/org/folio/circulation/support/http/server/JsonHttpResponse.java b/src/main/java/org/folio/circulation/support/http/server/JsonHttpResponse.java index d7f341a3ab..c9f20a0d7a 100644 --- a/src/main/java/org/folio/circulation/support/http/server/JsonHttpResponse.java +++ b/src/main/java/org/folio/circulation/support/http/server/JsonHttpResponse.java @@ -7,7 +7,9 @@ import io.vertx.core.http.HttpServerResponse; import io.vertx.core.json.Json; import io.vertx.core.json.JsonObject; +import lombok.extern.log4j.Log4j2; +@Log4j2 public class JsonHttpResponse implements HttpResponse { private final int statusCode; private final JsonObject body; @@ -41,6 +43,8 @@ public JsonHttpResponse(int statusCode, JsonObject body, String location) { @Override public void writeTo(HttpServerResponse response) { + log.info("writeTo:: {}", response); + log.info("writeTo:: {}", Json.encodePrettily(body)); String json = Json.encodePrettily(body); Buffer buffer = buffer(json, "UTF-8"); From b4cc193abe679e2297afa1ce848df11befc1b4be Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 23:19:15 +0530 Subject: [PATCH 22/38] CIRC-2100 Adding logs --- .../org/folio/circulation/domain/RequestRepresentation.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index 64c25db272..e039fe38be 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -267,7 +267,9 @@ private static void addPrintEventProperties(JsonObject request, PrintEventDetail } var printEvent = new JsonObject(); + log.info("count {}", printEventDetail.getCount()); printEvent.put("count", printEventDetail.getCount()); + log.info("lastPrintedDate {}", printEventDetail.getPrintEventDate()); printEvent.put("lastPrintedDate", printEventDetail.getPrintEventDate()); var user = printEventDetail.getUser(); From 945ea9bcb6464ad72ab5d4bc9ddb9127edd84f35 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 24 Jul 2024 23:52:12 +0530 Subject: [PATCH 23/38] CIRC-2100 Code Refactoring --- .../folio/circulation/domain/MultipleRecords.java | 4 +--- .../circulation/domain/RequestRepresentation.java | 12 ++++-------- .../support/http/server/JsonHttpResponse.java | 4 ---- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/MultipleRecords.java b/src/main/java/org/folio/circulation/domain/MultipleRecords.java index e43d2a425d..43cf488288 100644 --- a/src/main/java/org/folio/circulation/domain/MultipleRecords.java +++ b/src/main/java/org/folio/circulation/domain/MultipleRecords.java @@ -158,9 +158,7 @@ public JsonObject asJson(Function mapper, String recordsPropertyN final List mappedRecords = getRecords().stream() .map(mapper) .collect(Collectors.toList()); - log.info("asJson:: jsonObject {}", new JsonObject() - .put(recordsPropertyName, new JsonArray(mappedRecords)) - .put(TOTAL_RECORDS_PROPERTY_NAME, totalRecords)); + return new JsonObject() .put(recordsPropertyName, new JsonArray(mappedRecords)) .put(TOTAL_RECORDS_PROPERTY_NAME, totalRecords); diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index e039fe38be..d03727b397 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -36,7 +36,6 @@ public JsonObject extendedRepresentation(Request request) { addPrintEventProperties(requestRepresentation, request.getPrintEventDetail()); removeSearchIndexFields(requestRepresentation); - log.info("extendedRepresentation :: {}", requestRepresentation); return requestRepresentation; } @@ -267,10 +266,8 @@ private static void addPrintEventProperties(JsonObject request, PrintEventDetail } var printEvent = new JsonObject(); - log.info("count {}", printEventDetail.getCount()); - printEvent.put("count", printEventDetail.getCount()); - log.info("lastPrintedDate {}", printEventDetail.getPrintEventDate()); - printEvent.put("lastPrintedDate", printEventDetail.getPrintEventDate()); + write(printEvent, "count", printEventDetail.getCount()); + write(printEvent, "lastPrintedDate", printEventDetail.getPrintEventDate()); var user = printEventDetail.getUser(); if (user != null) { @@ -278,10 +275,9 @@ private static void addPrintEventProperties(JsonObject request, PrintEventDetail write(userSummary, "lastName", user.getLastName()); write(userSummary, "firstName", user.getFirstName()); write(userSummary, "middleName", user.getMiddleName()); - printEvent.put("lastPrintRequester", userSummary); + write(printEvent, "lastPrintRequester", userSummary); } - - request.put("printDetails", printEvent); + write(request, "printDetails", printEvent); } } diff --git a/src/main/java/org/folio/circulation/support/http/server/JsonHttpResponse.java b/src/main/java/org/folio/circulation/support/http/server/JsonHttpResponse.java index c9f20a0d7a..d7f341a3ab 100644 --- a/src/main/java/org/folio/circulation/support/http/server/JsonHttpResponse.java +++ b/src/main/java/org/folio/circulation/support/http/server/JsonHttpResponse.java @@ -7,9 +7,7 @@ import io.vertx.core.http.HttpServerResponse; import io.vertx.core.json.Json; import io.vertx.core.json.JsonObject; -import lombok.extern.log4j.Log4j2; -@Log4j2 public class JsonHttpResponse implements HttpResponse { private final int statusCode; private final JsonObject body; @@ -43,8 +41,6 @@ public JsonHttpResponse(int statusCode, JsonObject body, String location) { @Override public void writeTo(HttpServerResponse response) { - log.info("writeTo:: {}", response); - log.info("writeTo:: {}", Json.encodePrettily(body)); String json = Json.encodePrettily(body); Buffer buffer = buffer(json, "UTF-8"); From bed2f82241f26b1fd13b40659fe67358eba2fe67 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Thu, 25 Jul 2024 00:33:17 +0530 Subject: [PATCH 24/38] CIRC-2100 Code Refactoring --- .../org/folio/circulation/domain/RequestRepresentation.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index d03727b397..a5c6227e94 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -1,5 +1,6 @@ package org.folio.circulation.domain; +import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; import static java.util.Objects.isNull; import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toList; @@ -267,7 +268,7 @@ private static void addPrintEventProperties(JsonObject request, PrintEventDetail var printEvent = new JsonObject(); write(printEvent, "count", printEventDetail.getCount()); - write(printEvent, "lastPrintedDate", printEventDetail.getPrintEventDate()); + write(printEvent, "lastPrintedDate", ISO_ZONED_DATE_TIME.format(printEventDetail.getPrintEventDate())); var user = printEventDetail.getUser(); if (user != null) { From 273de17f6c9513ec2fc7f3c6385becee81a895b2 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Thu, 25 Jul 2024 00:41:42 +0530 Subject: [PATCH 25/38] CIRC-2100 Code Refactoring --- .../org/folio/circulation/domain/PrintEventDetail.java | 7 ++----- .../folio/circulation/domain/RequestRepresentation.java | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java index b52a440c30..65726d92d9 100644 --- a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java +++ b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java @@ -6,9 +6,6 @@ import lombok.With; import lombok.extern.log4j.Log4j2; -import java.time.ZonedDateTime; - -import static org.folio.circulation.support.json.JsonPropertyFetcher.getDateTimeProperty; import static org.folio.circulation.support.json.JsonPropertyFetcher.getIntegerProperty; import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; @@ -37,8 +34,8 @@ public int getCount() { return getIntegerProperty(representation, "count", 0); } - public ZonedDateTime getPrintEventDate() { - return getDateTimeProperty(representation, "printEventDate"); + public String getPrintEventDate() { + return getProperty(representation, "printEventDate"); } public User getUser() { diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index a5c6227e94..d03727b397 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -1,6 +1,5 @@ package org.folio.circulation.domain; -import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; import static java.util.Objects.isNull; import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toList; @@ -268,7 +267,7 @@ private static void addPrintEventProperties(JsonObject request, PrintEventDetail var printEvent = new JsonObject(); write(printEvent, "count", printEventDetail.getCount()); - write(printEvent, "lastPrintedDate", ISO_ZONED_DATE_TIME.format(printEventDetail.getPrintEventDate())); + write(printEvent, "lastPrintedDate", printEventDetail.getPrintEventDate()); var user = printEventDetail.getUser(); if (user != null) { From 6083d5ee6db62c69b3ae53eabdc3d3d6eb8154d3 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Thu, 25 Jul 2024 18:19:21 +0530 Subject: [PATCH 26/38] CIRC-2100 Fixing NPE --- .../storage/PrintEventsRepository.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index 714f5b576e..360fcc4552 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -15,6 +15,7 @@ import java.lang.invoke.MethodHandles; import java.util.Collection; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import static java.util.concurrent.CompletableFuture.completedFuture; @@ -59,6 +60,9 @@ public CompletableFuture>> findPrintEventDetails private CompletableFuture>> fetchAndMapPrintEventDetails( MultipleRecords multipleRequests) { var requestIds = multipleRequests.toKeys(Request::getId); + if (requestIds.isEmpty()) { + return completedFuture(succeeded(multipleRequests)); + } return fetchPrintDetailsByRequestIds(requestIds) .thenApply(printEventRecordsResult -> printEventRecordsResult .next(printEventRecords -> mapPrintEventDetailsToRequest(printEventRecords, multipleRequests))); @@ -66,10 +70,11 @@ private CompletableFuture>> fetchAndMapPrintEven private CompletableFuture validatePrintEventFeatureFlag() { return circulationSettingsRepository.findBy("query=name=printEventLogFeature") - .thenApply(res -> res.value().getRecords() - .stream() - .map(setting -> Boolean.valueOf(getProperty(setting.getValue(), "enablePrintLog"))) - .findFirst() + .thenApply(res -> Optional.ofNullable(res.value()) + .map(records -> records.getRecords().stream() + .map(setting -> Boolean.valueOf(getProperty(setting.getValue(), "enablePrintLog"))) + .findFirst() + .orElse(false)) .orElse(false)); } From 791bcf4a35493c5e5de2c03c06159da3c6e33cb2 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Thu, 25 Jul 2024 19:25:10 +0530 Subject: [PATCH 27/38] CIRC-2100 Fetching print event details only when required --- descriptors/ModuleDescriptor-template.json | 3 +- .../circulation/domain/PrintEventDetail.java | 7 ++- .../storage/requests/RequestRepository.java | 11 ++++- .../storage/users/UserRepository.java | 43 ++++++++++++++++--- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index ce90a5c4e0..5f421a1673 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -2066,7 +2066,8 @@ "addresstypes.collection.get", "usergroups.collection.get", "usergroups.item.get", - "print-events-storage.print-events-status.item.post" + "print-events-storage.print-events-status.item.post", + "circulation-storage.circulation-settings.collection.get" ], "visible": false }, diff --git a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java index 65726d92d9..b52a440c30 100644 --- a/src/main/java/org/folio/circulation/domain/PrintEventDetail.java +++ b/src/main/java/org/folio/circulation/domain/PrintEventDetail.java @@ -6,6 +6,9 @@ import lombok.With; import lombok.extern.log4j.Log4j2; +import java.time.ZonedDateTime; + +import static org.folio.circulation.support.json.JsonPropertyFetcher.getDateTimeProperty; import static org.folio.circulation.support.json.JsonPropertyFetcher.getIntegerProperty; import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; @@ -34,8 +37,8 @@ public int getCount() { return getIntegerProperty(representation, "count", 0); } - public String getPrintEventDate() { - return getProperty(representation, "printEventDate"); + public ZonedDateTime getPrintEventDate() { + return getDateTimeProperty(representation, "printEventDate"); } public User getUser() { diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java index 750b904252..9f85a9fb53 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java @@ -125,7 +125,8 @@ public static RequestRepository using( public CompletableFuture>> findBy(String query) { return requestsStorageClient.getManyWithRawQueryStringParameters(query) .thenApply(flatMapResult(this::mapResponseToRequests)) - .thenCompose(r -> r.after(this::fetchAdditionalFields)); + .thenCompose(r -> r.after(this::fetchAdditionalFields)) + .thenCompose(r -> r.after(this::fetchPrintEventDetails)); } CompletableFuture>> findBy(CqlQuery query, PageLimit pageLimit) { @@ -141,7 +142,6 @@ private CompletableFuture>> fetchAdditionalField return ofAsync(() -> requestRecords) .thenComposeAsync(requests -> itemRepository.fetchItemsFor(requests, Request::withItem)) - .thenComposeAsync(result -> result.after(printEventsRepository::findPrintEventDetails)) .thenComposeAsync(result -> result.after(loanRepository::findOpenLoansFor)) .thenComposeAsync(result -> result.after(servicePointRepository::findServicePointsForRequests)) .thenComposeAsync(result -> result.after(userRepository::findUsersForRequests)) @@ -149,6 +149,13 @@ private CompletableFuture>> fetchAdditionalField .thenComposeAsync(result -> result.after(instanceRepository::findInstancesForRequests)); } + private CompletableFuture>> fetchPrintEventDetails( + MultipleRecords requestRecords) { + return ofAsync(() -> requestRecords) + .thenComposeAsync(result -> result.after(printEventsRepository::findPrintEventDetails)) + .thenComposeAsync(result -> result.after(userRepository::findUsersForPrintEvents)); + } + CompletableFuture>> findByWithoutItems( CqlQuery query, PageLimit pageLimit) { diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java index 8e8256f990..cae35c4471 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java @@ -239,6 +239,18 @@ public CompletableFuture>> findUsersForRequests( matchUsersToRequests(request, multipleUsers))))); } + public CompletableFuture>> findUsersForPrintEvents( + MultipleRecords multipleRequests) { + + log.debug("findUsersForRequests:: parameters multipleRequests: {}", + () -> multipleRecordsAsString(multipleRequests)); + return findUsersForPrintEvents(multipleRequests.getRecords()) + .thenApply(multipleUsersResult -> multipleUsersResult.next( + multipleUsers -> of(() -> + multipleRequests.mapRecords(request -> + matchUsersToPrintEvents(request, multipleUsers))))); + } + public CompletableFuture>> findUsersByRequests( Collection requests) { @@ -249,6 +261,22 @@ public CompletableFuture>> findUsersByRequests( .distinct() .collect(Collectors.toList()); + return fetchUsers(usersToFetch); + } + + public CompletableFuture>> findUsersForPrintEvents( + Collection requests) { + log.debug("findUsersForPrintEvents:: parameters requests: {}", () -> collectionAsString(requests)); + final List usersToFetch = requests.stream() + .filter(request -> request.getPrintEventDetail() != null && request.getPrintEventDetail().getUserId() != null) + .map(request -> request.getPrintEventDetail().getUserId()) + .distinct() + .collect(Collectors.toList()); + + return fetchUsers(usersToFetch); + } + + private CompletableFuture>> fetchUsers(List usersToFetch) { if (usersToFetch.isEmpty()) { log.info("findUsersByRequests:: no users to fetch"); return completedFuture(succeeded(MultipleRecords.empty())); @@ -272,10 +300,6 @@ private ArrayList getUsersFromRequest(Request request) { usersToFetch.add(request.getProxyUserId()); } - if (request.getPrintEventDetail() != null && request.getPrintEventDetail().getUserId() != null) { - usersToFetch.add(request.getPrintEventDetail().getUserId()); - } - return usersToFetch; } @@ -287,7 +311,16 @@ private Request matchUsersToRequests( return request .withRequester(userMap.getOrDefault(request.getUserId(), null)) - .withProxy(userMap.getOrDefault(request.getProxyUserId(), null)) + .withProxy(userMap.getOrDefault(request.getProxyUserId(), null)); + } + + private Request matchUsersToPrintEvents( + Request request, + MultipleRecords users) { + + final Map userMap = users.toMap(User::getId); + + return request .withPrintEventDetail(mapUserToPrintEventDetails(request, userMap)); } From 574a9267cab9d1d35e6d7b9e17cf3338de6dce3c Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Thu, 25 Jul 2024 22:13:20 +0530 Subject: [PATCH 28/38] CIRC-2100 Avoiding extra user API call --- .../storage/PrintEventsRepository.java | 8 +++- .../storage/requests/RequestRepository.java | 9 ++-- .../storage/users/UserRepository.java | 43 +++---------------- 3 files changed, 16 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index 360fcc4552..10ef85e8c3 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -59,6 +59,8 @@ public CompletableFuture>> findPrintEventDetails private CompletableFuture>> fetchAndMapPrintEventDetails( MultipleRecords multipleRequests) { + log.debug("fetchAndMapPrintEventDetails:: parameters multipleRequests: {}", + () -> multipleRecordsAsString(multipleRequests)); var requestIds = multipleRequests.toKeys(Request::getId); if (requestIds.isEmpty()) { return completedFuture(succeeded(multipleRequests)); @@ -88,10 +90,12 @@ private CompletableFuture validatePrintEventFeatureFlag() { private Result> mapPrintEventDetailsToRequest( MultipleRecords printEventDetails, MultipleRecords requests) { - log.info("mapPrintEventDetailsToRequest:: Mapping print event details {} with requests {}", + log.debug("mapPrintEventDetailsToRequest:: Mapping print event details {} with requests {}", () -> multipleRecordsAsString(printEventDetails), () -> multipleRecordsAsString(requests)); Map printEventDetailMap = printEventDetails.toMap(PrintEventDetail::getRequestId); - return of(() -> requests.mapRecords(request -> request.withPrintEventDetail(printEventDetailMap.getOrDefault(request.getId(), null)))); + return of(() -> + requests.mapRecords(request -> request + .withPrintEventDetail(printEventDetailMap.getOrDefault(request.getId(), null)))); } } diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java index 9f85a9fb53..c17aa06dc5 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/requests/RequestRepository.java @@ -125,8 +125,8 @@ public static RequestRepository using( public CompletableFuture>> findBy(String query) { return requestsStorageClient.getManyWithRawQueryStringParameters(query) .thenApply(flatMapResult(this::mapResponseToRequests)) - .thenCompose(r -> r.after(this::fetchAdditionalFields)) - .thenCompose(r -> r.after(this::fetchPrintEventDetails)); + .thenCompose(r -> r.after(this::fetchPrintEventDetails)) + .thenCompose(r -> r.after(this::fetchAdditionalFields)); } CompletableFuture>> findBy(CqlQuery query, PageLimit pageLimit) { @@ -151,9 +151,10 @@ private CompletableFuture>> fetchAdditionalField private CompletableFuture>> fetchPrintEventDetails( MultipleRecords requestRecords) { + log.debug("fetchPrintEventDetails:: Fetching print event details for requestRecords: {}", + ()-> multipleRecordsAsString(requestRecords)); return ofAsync(() -> requestRecords) - .thenComposeAsync(result -> result.after(printEventsRepository::findPrintEventDetails)) - .thenComposeAsync(result -> result.after(userRepository::findUsersForPrintEvents)); + .thenComposeAsync(result -> result.after(printEventsRepository::findPrintEventDetails)); } CompletableFuture>> findByWithoutItems( diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java index cae35c4471..8e8256f990 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/users/UserRepository.java @@ -239,18 +239,6 @@ public CompletableFuture>> findUsersForRequests( matchUsersToRequests(request, multipleUsers))))); } - public CompletableFuture>> findUsersForPrintEvents( - MultipleRecords multipleRequests) { - - log.debug("findUsersForRequests:: parameters multipleRequests: {}", - () -> multipleRecordsAsString(multipleRequests)); - return findUsersForPrintEvents(multipleRequests.getRecords()) - .thenApply(multipleUsersResult -> multipleUsersResult.next( - multipleUsers -> of(() -> - multipleRequests.mapRecords(request -> - matchUsersToPrintEvents(request, multipleUsers))))); - } - public CompletableFuture>> findUsersByRequests( Collection requests) { @@ -261,22 +249,6 @@ public CompletableFuture>> findUsersByRequests( .distinct() .collect(Collectors.toList()); - return fetchUsers(usersToFetch); - } - - public CompletableFuture>> findUsersForPrintEvents( - Collection requests) { - log.debug("findUsersForPrintEvents:: parameters requests: {}", () -> collectionAsString(requests)); - final List usersToFetch = requests.stream() - .filter(request -> request.getPrintEventDetail() != null && request.getPrintEventDetail().getUserId() != null) - .map(request -> request.getPrintEventDetail().getUserId()) - .distinct() - .collect(Collectors.toList()); - - return fetchUsers(usersToFetch); - } - - private CompletableFuture>> fetchUsers(List usersToFetch) { if (usersToFetch.isEmpty()) { log.info("findUsersByRequests:: no users to fetch"); return completedFuture(succeeded(MultipleRecords.empty())); @@ -300,6 +272,10 @@ private ArrayList getUsersFromRequest(Request request) { usersToFetch.add(request.getProxyUserId()); } + if (request.getPrintEventDetail() != null && request.getPrintEventDetail().getUserId() != null) { + usersToFetch.add(request.getPrintEventDetail().getUserId()); + } + return usersToFetch; } @@ -311,16 +287,7 @@ private Request matchUsersToRequests( return request .withRequester(userMap.getOrDefault(request.getUserId(), null)) - .withProxy(userMap.getOrDefault(request.getProxyUserId(), null)); - } - - private Request matchUsersToPrintEvents( - Request request, - MultipleRecords users) { - - final Map userMap = users.toMap(User::getId); - - return request + .withProxy(userMap.getOrDefault(request.getProxyUserId(), null)) .withPrintEventDetail(mapUserToPrintEventDetails(request, userMap)); } From 391c507dab80941874bf5c09619a2c105d2490cd Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Fri, 26 Jul 2024 11:53:17 +0530 Subject: [PATCH 29/38] CIRC-2099 removed loggers --- .../org/folio/circulation/domain/CirculationSetting.java | 1 - .../storage/CirculationSettingsRepository.java | 9 ++------- .../folio/circulation/resources/PrintEventsResource.java | 7 +++---- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/CirculationSetting.java b/src/main/java/org/folio/circulation/domain/CirculationSetting.java index 4f5c67342c..03f254f1ed 100644 --- a/src/main/java/org/folio/circulation/domain/CirculationSetting.java +++ b/src/main/java/org/folio/circulation/domain/CirculationSetting.java @@ -39,7 +39,6 @@ public class CirculationSetting { private final JsonObject value; public static CirculationSetting from(JsonObject representation) { - log.info("from {}", representation); final var id = getProperty(representation, ID_FIELD); final var name = getProperty(representation, NAME_FIELD); final var value = getObjectProperty(representation, VALUE_FIELD); diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java index 809c71adb2..39f2ec1bff 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java @@ -40,13 +40,8 @@ public CompletableFuture> getById(String id) { public CompletableFuture>> findBy(String query) { return circulationSettingsStorageClient.getManyWithRawQueryStringParameters(query) - .thenApply(flatMapResult(response -> { - log.info("************* {}", response); - log.info(MultipleRecords.from(response, CirculationSetting::from, RECORDS_PROPERTY_NAME).value().getRecords()); - return MultipleRecords.from(response, CirculationSetting::from, RECORDS_PROPERTY_NAME); - } - )); - + .thenApply(flatMapResult(response -> + MultipleRecords.from(response, CirculationSetting::from, RECORDS_PROPERTY_NAME))); } public CompletableFuture> create( diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index 57a69fd9cf..72ba78fcd1 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -85,10 +85,9 @@ void create(RoutingContext routingContext) { private static Function>> validatePrintEventFeatureFlag( CirculationSettingsRepository circulationSettingsRepository) { return printEventRequest -> circulationSettingsRepository.findBy(PRINT_EVENT_FLAG_QUERY) - .thenApply(result -> { - log.info("validatePrintEventFeatureFlag:: result value {}", result.value().getRecords()); - return handleCirculationSettingResult(result.map(MultipleRecords::getRecords), printEventRequest); - }); + .thenApply(result -> + handleCirculationSettingResult(result.map(MultipleRecords::getRecords), printEventRequest) + ); } private static Result handleCirculationSettingResult(Result> result, From c7d947e8f5037676964b4212856d5d9fe0347075 Mon Sep 17 00:00:00 2001 From: SreejaMangarapu Date: Fri, 26 Jul 2024 11:58:19 +0530 Subject: [PATCH 30/38] CIRC-2099 removed loggers --- .../infrastructure/storage/CirculationSettingsRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java index 39f2ec1bff..8125f1761b 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/CirculationSettingsRepository.java @@ -41,7 +41,7 @@ public CompletableFuture> getById(String id) { public CompletableFuture>> findBy(String query) { return circulationSettingsStorageClient.getManyWithRawQueryStringParameters(query) .thenApply(flatMapResult(response -> - MultipleRecords.from(response, CirculationSetting::from, RECORDS_PROPERTY_NAME))); + MultipleRecords.from(response, CirculationSetting::from, RECORDS_PROPERTY_NAME))); } public CompletableFuture> create( From 6304446b9e26c130774b3e9e2a7efdff86b539d5 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Tue, 30 Jul 2024 00:28:53 +0530 Subject: [PATCH 31/38] CIRC-2100 Adding test cases --- descriptors/ModuleDescriptor-template.json | 2 +- ramls/examples/request.json | 9 ++ ramls/request.json | 40 +++++ .../api/printEvents/PrintEventsTests.java | 147 ++++++++++++++++-- .../java/api/support/fakes/FakeOkapi.java | 2 + .../fakes/FakePrintEventStatusModule.java | 86 ++++++++++ 6 files changed, 275 insertions(+), 11 deletions(-) create mode 100644 src/test/java/api/support/fakes/FakePrintEventStatusModule.java diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 5f421a1673..f2e3bb42e7 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -185,7 +185,7 @@ }, { "id": "circulation", - "version": "14.3", + "version": "14.4", "handlers": [ { "methods": [ diff --git a/ramls/examples/request.json b/ramls/examples/request.json index efeca2d28b..228c97f1b7 100644 --- a/ramls/examples/request.json +++ b/ramls/examples/request.json @@ -45,5 +45,14 @@ "callNumber": "F16.H37 A2 9001" }, "pickupServicePointName": "Circ Desk 1" + }, + "printDetails": { + "count": 4, + "lastPrintedDate": "2024-07-29T11:54:07.000Z", + "lastPrintRequester": { + "lastName": "lastName", + "firstName": "firstName", + "middleName": "middleName" + } } } diff --git a/ramls/request.json b/ramls/request.json index 9e38fe6c7f..1b80913dbb 100644 --- a/ramls/request.json +++ b/ramls/request.json @@ -358,6 +358,46 @@ } } }, + "printDetails": { + "description": "The print details of the request", + "type": "object", + "readonly": true, + "properties": { + "count": { + "description": "Total no of times the request is printed", + "type": "integer", + "readOnly": true + }, + "lastPrintedDate": { + "description": "Recent printed time of the request", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "lastPrintRequester": { + "description": "Details of the User who printed the request recently", + "readonly": true, + "type": "object", + "properties": { + "firstName": { + "description": "first name of the user", + "type": "string", + "readonly": true + }, + "lastName": { + "description": "last name of the user", + "type": "string", + "readonly": true + }, + "middleName": { + "description": "middle name of the user", + "type": "string", + "readonly": true + } + } + } + } + }, "tags": { "type": "object", "description": "Tags", diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index 0d8b03bce7..bdc301bca3 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -3,23 +3,39 @@ import api.support.APITests; import api.support.builders.CirculationSettingBuilder; import api.support.builders.RequestBuilder; +import api.support.http.IndividualResource; +import api.support.http.UserResource; import io.vertx.core.json.JsonObject; import org.folio.circulation.support.http.client.Response; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.stream.IntStream; +import static api.support.http.CqlQuery.exactMatch; import static api.support.http.InterfaceUrls.printEventsUrl; import static api.support.matchers.ResponseStatusCodeMatcher.hasStatus; import static org.folio.HttpStatus.HTTP_CREATED; import static org.folio.HttpStatus.HTTP_UNPROCESSABLE_ENTITY; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; class PrintEventsTests extends APITests { + private IndividualResource servicePointResource; + private UserResource userResource; + + @BeforeEach + void executeBefore() { + userResource = usersFixture.charlotte(); + servicePointResource = servicePointsFixture.cd1(); + circulationSettingsClient.deleteAll(); + } @Test void postPrintEventsTest() { @@ -27,12 +43,96 @@ void postPrintEventsTest() { .withName("printEventLogFeature") .withValue(new JsonObject().put("enablePrintLog", true))); JsonObject printRequest = getPrintEvent(); - printRequest.put("requestIds", createOneHundredRequests()); + printRequest.put("requestIds", createMultipleRequests(100, "test-")); System.out.println(printRequest.getString("requestIds")); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_CREATED)); } + @Test + void postPrintEventsAndFetchPrintDetailsInRequestApi() { + var itemBarcodePrefix = "itemBarcode-"; + + assertThat("Circulation settings enabled", circulationSettingsClient.getAll().isEmpty()); + + // creating 2 different requests and assert request details without enabling printEvent feature + var uuidList = createMultipleRequests(2, itemBarcodePrefix); + JsonObject requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + JsonObject requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should be null for request1 because the print event feature is not enabled", + requestRepresentation1.getJsonObject("printDetails"), Matchers.nullValue()); + assertThat("printDetails should be null for request2 because the print event feature is not enabled", + requestRepresentation2.getJsonObject("printDetails"), Matchers.nullValue()); + + // Enabling printEvent feature and assert request details. + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("printEventLogFeature") + .withValue(new JsonObject().put("enablePrintLog", true))); + requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should be null for request1 because the request is not printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.nullValue()); + assertThat("printDetails should be null for request2 because the request is not printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.nullValue()); + + // Printing both request1 and request2 + JsonObject printRequest = getPrintEvent(); + printRequest.put("requestIds", uuidList); + printRequest.put("requesterId", userResource.getId()); + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should not be null for request1 because the request is printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); + assertThat("printDetails should not be null for request2 because the request is printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); + assertPrintDetails(requestRepresentation1, 1, "2024-06-25T11:54:07.000Z"); + assertPrintDetails(requestRepresentation2, 1, "2024-06-25T11:54:07.000Z"); + + // Print both the request id again with same user. + // In this case, we will get the latest print event date and the count is increased + printRequest.put("printEventDate", "2024-06-25T14:54:07.000Z"); + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should not be null for request1 because the request is printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); + assertThat("printDetails should not be null for request2 because the request is printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); + assertPrintDetails(requestRepresentation1, 2, "2024-06-25T14:54:07.000Z"); + assertPrintDetails(requestRepresentation2, 2, "2024-06-25T14:54:07.000Z"); + + // Print only request1 with unknown user id. + // In this case, request representation won't contain lastPrintRequester detail + printRequest.put("requesterId", UUID.randomUUID()); + printRequest.put("requestIds", List.of(uuidList.get(0))); + printRequest.put("printEventDate", "2024-06-25T14:59:07.000Z"); + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); + assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); + assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); + assertThat("printDetails should not be null for request1 because the request is printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); + assertThat("printDetails should not be null for request2 because the request is printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); + assertPrintDetails(requestRepresentation2, 2, "2024-06-25T14:54:07.000Z"); + assertThat(requestRepresentation1.getJsonObject("printDetails").getInteger("count"), is(3)); + assertThat(requestRepresentation1.getJsonObject("printDetails").getString("lastPrintedDate"), + is("2024-06-25T14:59:07.000Z")); + assertThat("lastPrintRequester object should be null because we used random uuid for user id while printing", + requestRepresentation1.getJsonObject("printDetails").getJsonObject("lastPrintRequester"), + Matchers.nullValue()); + } + @Test void postPrintEventsWhenCirculationSettingIsNotPresentTest() { JsonObject printRequest = getPrintEvent(); @@ -74,8 +174,8 @@ void postPrintEventsWithInvalidRequestId() { .withName("printEventLogFeature") .withValue(new JsonObject().put("enablePrintLog", true))); JsonObject printRequest = getPrintEvent(); - List requestIds = new ArrayList<>(createOneHundredRequests()); - requestIds.add(UUID.randomUUID()); + List requestIds = new ArrayList<>(createMultipleRequests(10, "invalid-")); + requestIds.add(UUID.randomUUID().toString()); printRequest.put("requestIds", requestIds); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); @@ -111,19 +211,46 @@ private JsonObject getPrintEvent() { return new JsonObject() .put("requesterId", "5f5751b4-e352-4121-adca-204b0c2aec43") .put("requesterName", "requester") - .put("printEventDate", "2024-06-25T14:30:00Z"); + .put("printEventDate", "2024-06-25T11:54:07.000Z"); } - private List createOneHundredRequests() { - final UUID pickupServicePointId = servicePointsFixture.cd1().getId(); + private List createMultipleRequests(int noOfRequests, String itemBarcode) { - return IntStream.range(0, 100).mapToObj(notUsed -> requestsFixture.place( + return IntStream.range(0, noOfRequests).mapToObj(i -> requestsFixture.place( new RequestBuilder() .open() .page() - .forItem(itemsFixture.basedUponSmallAngryPlanet()) - .by(usersFixture.charlotte()) + .forItem(itemsFixture.basedUponSmallAngryPlanet(itemBarcode + i)) + .by(userResource) .fulfillToHoldShelf() - .withPickupServicePointId(pickupServicePointId)).getId()).toList(); + .withRequestExpiration(LocalDate.of(2024, 7, 30)) + .withHoldShelfExpiration(LocalDate.of(2024, 8, 15)) + .withPickupServicePointId(servicePointResource.getId())).getId().toString()).toList(); + } + + private void assertRequestDetails(JsonObject representation, String id, String barcodeName) { + assertThat(representation.getString("id"), is(id)); + assertThat(representation.getString("requestType"), is("Page")); + assertThat(representation.getString("requestLevel"), is("Item")); + assertThat(representation.getString("requestDate"), is("2017-07-15T09:35:27.000Z")); + assertThat(representation.getJsonObject("item").getString("barcode"), is(barcodeName)); + assertThat(representation.getString("fulfillmentPreference"), is("Hold Shelf")); + assertThat(representation.getString("requestExpirationDate"), is("2024-07-30T23:59:59.000Z")); + assertThat(representation.getString("holdShelfExpirationDate"), is("2024-08-15")); + assertThat(representation.getString("status"), is("Open - Not yet filled")); + assertThat(representation.getString("pickupServicePointId"), is(servicePointResource.getId().toString())); + } + + private void assertPrintDetails(JsonObject representation, int count, String printEventDate) { + var printDetailObject = representation.getJsonObject("printDetails"); + var lastPrintRequesterObject = printDetailObject.getJsonObject("lastPrintRequester"); + assertThat(printDetailObject.getInteger("count"), is(count)); + assertThat(printDetailObject.getString("lastPrintedDate"), is(printEventDate)); + assertThat(lastPrintRequesterObject.getString("middleName"), + is(userResource.getJson().getJsonObject("personal").getString("middleName"))); + assertThat(lastPrintRequesterObject.getString("lastName"), + is(userResource.getJson().getJsonObject("personal").getString("lastName"))); + assertThat(lastPrintRequesterObject.getString("firstName"), + is(userResource.getJson().getJsonObject("personal").getString("firstName"))); } } diff --git a/src/test/java/api/support/fakes/FakeOkapi.java b/src/test/java/api/support/fakes/FakeOkapi.java index 1ed5b8f5b0..c146982ce8 100644 --- a/src/test/java/api/support/fakes/FakeOkapi.java +++ b/src/test/java/api/support/fakes/FakeOkapi.java @@ -427,6 +427,8 @@ public void start(Promise startFuture) throws IOException { .withChangeMetadata() .create().register(router); + new FakePrintEventStatusModule().register(router); + new FakeFeeFineOperationsModule().register(router); server.requestHandler(router) diff --git a/src/test/java/api/support/fakes/FakePrintEventStatusModule.java b/src/test/java/api/support/fakes/FakePrintEventStatusModule.java new file mode 100644 index 0000000000..470a6e5924 --- /dev/null +++ b/src/test/java/api/support/fakes/FakePrintEventStatusModule.java @@ -0,0 +1,86 @@ +package api.support.fakes; + +import io.vertx.core.buffer.Buffer; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import lombok.SneakyThrows; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static api.support.APITestContext.getTenantId; +import static api.support.fakes.Storage.getStorage; +import static org.folio.HttpStatus.HTTP_UNPROCESSABLE_ENTITY; +import static org.folio.circulation.support.http.server.JsonHttpResponse.ok; + +public class FakePrintEventStatusModule { + + @SneakyThrows + public void register(Router router) { + router.post("/print-events-storage/print-events-status") + .handler(this::handlePrintEventStatusRequest); + + } + + private void handlePrintEventStatusRequest(RoutingContext routingContext) { + System.out.println("handlePrintEventStatusRequest **************"); + var request = routingContext.body().asJsonObject(); + var requestIds = request.getJsonArray("requestIds"); + if (requestIds.isEmpty()) { + Buffer buffer = Buffer.buffer( + "Size must be 1", "UTF-8"); + routingContext.response() + .setStatusCode(HTTP_UNPROCESSABLE_ENTITY.toInt()) + .putHeader("content-type", "text/plain; charset=utf-8") + .putHeader("content-length", Integer.toString(buffer.length())) + .write(buffer); + routingContext.response().end(); + } + var jsonObjectList = new ArrayList<>(getStorage() + .getTenantResources("/print-events-storage/print-events-entry", getTenantId()) + .values() + .stream() + .toList()); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"); + // Sorting jsonObjectList based on PrintEventDate so that it will always return latest printEventDetail + jsonObjectList.sort((obj1, obj2) -> { + try { + Date date1 = dateFormat.parse(obj1.getString("printEventDate")); + Date date2 = dateFormat.parse(obj2.getString("printEventDate")); + return date2.compareTo(date1); + } catch (ParseException e) { + throw new RuntimeException(e); + } + }); + + Map> groupByRequestIdMap = new LinkedHashMap<>(); + requestIds.forEach(requestId -> { + var requestList = jsonObjectList.stream().filter(jsonObject -> + jsonObject.getJsonArray("requestIds").contains(requestId)) + .toList(); + groupByRequestIdMap.put((String) requestId, requestList); + }); + + var jsonObjectResponse = new JsonObject(); + var printEventStatusResponses = new ArrayList<>(); + jsonObjectResponse.put("printEventsStatusResponses", printEventStatusResponses); + requestIds.forEach(id -> { + var requestDetail = groupByRequestIdMap.get(id); + if (requestDetail !=null && !requestDetail.isEmpty()) { + var object = new JsonObject() + .put("requestId", id) + .put("count", requestDetail.size()) + .put("requesterId", requestDetail.get(0).getString("requesterId")) + .put("printEventDate", requestDetail.get(0).getString("printEventDate")); + printEventStatusResponses.add(object); + } + }); + ok(jsonObjectResponse).writeTo(routingContext.response()); + } +} From 02ecd1a418e82375856fc63e561f9f3baa7d973a Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Tue, 30 Jul 2024 00:29:50 +0530 Subject: [PATCH 32/38] CIRC-2100 Adding test cases --- .../java/api/support/fakes/FakePrintEventStatusModule.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/test/java/api/support/fakes/FakePrintEventStatusModule.java b/src/test/java/api/support/fakes/FakePrintEventStatusModule.java index 470a6e5924..628fb2203c 100644 --- a/src/test/java/api/support/fakes/FakePrintEventStatusModule.java +++ b/src/test/java/api/support/fakes/FakePrintEventStatusModule.java @@ -29,7 +29,6 @@ public void register(Router router) { } private void handlePrintEventStatusRequest(RoutingContext routingContext) { - System.out.println("handlePrintEventStatusRequest **************"); var request = routingContext.body().asJsonObject(); var requestIds = request.getJsonArray("requestIds"); if (requestIds.isEmpty()) { @@ -58,7 +57,6 @@ private void handlePrintEventStatusRequest(RoutingContext routingContext) { throw new RuntimeException(e); } }); - Map> groupByRequestIdMap = new LinkedHashMap<>(); requestIds.forEach(requestId -> { var requestList = jsonObjectList.stream().filter(jsonObject -> @@ -66,13 +64,12 @@ private void handlePrintEventStatusRequest(RoutingContext routingContext) { .toList(); groupByRequestIdMap.put((String) requestId, requestList); }); - var jsonObjectResponse = new JsonObject(); var printEventStatusResponses = new ArrayList<>(); jsonObjectResponse.put("printEventsStatusResponses", printEventStatusResponses); requestIds.forEach(id -> { var requestDetail = groupByRequestIdMap.get(id); - if (requestDetail !=null && !requestDetail.isEmpty()) { + if (requestDetail != null && !requestDetail.isEmpty()) { var object = new JsonObject() .put("requestId", id) .put("count", requestDetail.size()) From dac2a0e52093f157c1c59339f637a467b2fdf743 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Tue, 30 Jul 2024 13:13:01 +0530 Subject: [PATCH 33/38] CIRC-2100 Adding and refactoring test cases --- .../domain/RequestRepresentation.java | 3 +- .../storage/PrintEventsRepository.java | 4 +- .../api/printEvents/PrintEventsTests.java | 148 ++------------- .../requests/RequestsAPICreationTests.java | 168 ++++++++++++++++++ .../fakes/FakePrintEventStatusModule.java | 80 ++++----- 5 files changed, 223 insertions(+), 180 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index d03727b397..df5811fa0a 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -261,7 +261,8 @@ private static void removeSearchIndexFields(JsonObject request) { private static void addPrintEventProperties(JsonObject request, PrintEventDetail printEventDetail) { if (printEventDetail == null) { - log.info("addPrintEventProperties:: printEvent property is null for requestId {}", request.getString("id")); + String msg = "addPrintEventProperties:: printEvent property is null for requestId {}"; + log.info(msg, request.getString("id")); return; } diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index 10ef85e8c3..d6264ae9d5 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -53,7 +53,8 @@ public CompletableFuture>> findPrintEventDetails log.debug("findPrintEventDetails:: parameters multipleRequests: {}", () -> multipleRecordsAsString(multipleRequests)); return validatePrintEventFeatureFlag() - .thenCompose(isEnabled -> isEnabled ? fetchAndMapPrintEventDetails(multipleRequests) + .thenCompose(isEnabled -> Boolean.TRUE.equals(isEnabled) ? + fetchAndMapPrintEventDetails(multipleRequests) : completedFuture(succeeded(multipleRequests))); } @@ -71,6 +72,7 @@ private CompletableFuture>> fetchAndMapPrintEven } private CompletableFuture validatePrintEventFeatureFlag() { + log.debug("validatePrintEventFeatureFlag:: Fetching and validating enablePrintLog flag from settings"); return circulationSettingsRepository.findBy("query=name=printEventLogFeature") .thenApply(res -> Optional.ofNullable(res.value()) .map(records -> records.getRecords().stream() diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index bdc301bca3..4459ad504c 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -3,39 +3,23 @@ import api.support.APITests; import api.support.builders.CirculationSettingBuilder; import api.support.builders.RequestBuilder; -import api.support.http.IndividualResource; -import api.support.http.UserResource; import io.vertx.core.json.JsonObject; import org.folio.circulation.support.http.client.Response; -import org.hamcrest.Matchers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.stream.IntStream; -import static api.support.http.CqlQuery.exactMatch; import static api.support.http.InterfaceUrls.printEventsUrl; import static api.support.matchers.ResponseStatusCodeMatcher.hasStatus; import static org.folio.HttpStatus.HTTP_CREATED; import static org.folio.HttpStatus.HTTP_UNPROCESSABLE_ENTITY; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; class PrintEventsTests extends APITests { - private IndividualResource servicePointResource; - private UserResource userResource; - - @BeforeEach - void executeBefore() { - userResource = usersFixture.charlotte(); - servicePointResource = servicePointsFixture.cd1(); - circulationSettingsClient.deleteAll(); - } @Test void postPrintEventsTest() { @@ -43,96 +27,11 @@ void postPrintEventsTest() { .withName("printEventLogFeature") .withValue(new JsonObject().put("enablePrintLog", true))); JsonObject printRequest = getPrintEvent(); - printRequest.put("requestIds", createMultipleRequests(100, "test-")); - System.out.println(printRequest.getString("requestIds")); + printRequest.put("requestIds", createOneHundredRequests()); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_CREATED)); } - @Test - void postPrintEventsAndFetchPrintDetailsInRequestApi() { - var itemBarcodePrefix = "itemBarcode-"; - - assertThat("Circulation settings enabled", circulationSettingsClient.getAll().isEmpty()); - - // creating 2 different requests and assert request details without enabling printEvent feature - var uuidList = createMultipleRequests(2, itemBarcodePrefix); - JsonObject requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); - JsonObject requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); - assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); - assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); - assertThat("printDetails should be null for request1 because the print event feature is not enabled", - requestRepresentation1.getJsonObject("printDetails"), Matchers.nullValue()); - assertThat("printDetails should be null for request2 because the print event feature is not enabled", - requestRepresentation2.getJsonObject("printDetails"), Matchers.nullValue()); - - // Enabling printEvent feature and assert request details. - circulationSettingsClient.create(new CirculationSettingBuilder() - .withName("printEventLogFeature") - .withValue(new JsonObject().put("enablePrintLog", true))); - requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); - requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); - assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); - assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); - assertThat("printDetails should be null for request1 because the request is not printed", - requestRepresentation1.getJsonObject("printDetails"), Matchers.nullValue()); - assertThat("printDetails should be null for request2 because the request is not printed", - requestRepresentation2.getJsonObject("printDetails"), Matchers.nullValue()); - - // Printing both request1 and request2 - JsonObject printRequest = getPrintEvent(); - printRequest.put("requestIds", uuidList); - printRequest.put("requesterId", userResource.getId()); - restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); - requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); - requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); - assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); - assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); - assertThat("printDetails should not be null for request1 because the request is printed", - requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); - assertThat("printDetails should not be null for request2 because the request is printed", - requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); - assertPrintDetails(requestRepresentation1, 1, "2024-06-25T11:54:07.000Z"); - assertPrintDetails(requestRepresentation2, 1, "2024-06-25T11:54:07.000Z"); - - // Print both the request id again with same user. - // In this case, we will get the latest print event date and the count is increased - printRequest.put("printEventDate", "2024-06-25T14:54:07.000Z"); - restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); - requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); - requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); - assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); - assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); - assertThat("printDetails should not be null for request1 because the request is printed", - requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); - assertThat("printDetails should not be null for request2 because the request is printed", - requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); - assertPrintDetails(requestRepresentation1, 2, "2024-06-25T14:54:07.000Z"); - assertPrintDetails(requestRepresentation2, 2, "2024-06-25T14:54:07.000Z"); - - // Print only request1 with unknown user id. - // In this case, request representation won't contain lastPrintRequester detail - printRequest.put("requesterId", UUID.randomUUID()); - printRequest.put("requestIds", List.of(uuidList.get(0))); - printRequest.put("printEventDate", "2024-06-25T14:59:07.000Z"); - restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); - requestRepresentation1 = requestsClient.getMany(exactMatch("id", uuidList.get(0))).getFirst(); - requestRepresentation2 = requestsClient.getMany(exactMatch("id", uuidList.get(1))).getFirst(); - assertRequestDetails(requestRepresentation1, uuidList.get(0), itemBarcodePrefix+0); - assertRequestDetails(requestRepresentation2, uuidList.get(1), itemBarcodePrefix+1); - assertThat("printDetails should not be null for request1 because the request is printed", - requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); - assertThat("printDetails should not be null for request2 because the request is printed", - requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); - assertPrintDetails(requestRepresentation2, 2, "2024-06-25T14:54:07.000Z"); - assertThat(requestRepresentation1.getJsonObject("printDetails").getInteger("count"), is(3)); - assertThat(requestRepresentation1.getJsonObject("printDetails").getString("lastPrintedDate"), - is("2024-06-25T14:59:07.000Z")); - assertThat("lastPrintRequester object should be null because we used random uuid for user id while printing", - requestRepresentation1.getJsonObject("printDetails").getJsonObject("lastPrintRequester"), - Matchers.nullValue()); - } - @Test void postPrintEventsWhenCirculationSettingIsNotPresentTest() { JsonObject printRequest = getPrintEvent(); @@ -174,8 +73,8 @@ void postPrintEventsWithInvalidRequestId() { .withName("printEventLogFeature") .withValue(new JsonObject().put("enablePrintLog", true))); JsonObject printRequest = getPrintEvent(); - List requestIds = new ArrayList<>(createMultipleRequests(10, "invalid-")); - requestIds.add(UUID.randomUUID().toString()); + List requestIds = new ArrayList<>(createOneHundredRequests()); + requestIds.add(UUID.randomUUID()); printRequest.put("requestIds", requestIds); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); assertThat(response, hasStatus(HTTP_UNPROCESSABLE_ENTITY)); @@ -211,46 +110,19 @@ private JsonObject getPrintEvent() { return new JsonObject() .put("requesterId", "5f5751b4-e352-4121-adca-204b0c2aec43") .put("requesterName", "requester") - .put("printEventDate", "2024-06-25T11:54:07.000Z"); + .put("printEventDate", "2024-06-25T14:30:00Z"); } - private List createMultipleRequests(int noOfRequests, String itemBarcode) { + private List createOneHundredRequests() { + final UUID pickupServicePointId = servicePointsFixture.cd1().getId(); - return IntStream.range(0, noOfRequests).mapToObj(i -> requestsFixture.place( + return IntStream.range(0, 100).mapToObj(notUsed -> requestsFixture.place( new RequestBuilder() .open() .page() - .forItem(itemsFixture.basedUponSmallAngryPlanet(itemBarcode + i)) - .by(userResource) + .forItem(itemsFixture.basedUponSmallAngryPlanet()) + .by(usersFixture.charlotte()) .fulfillToHoldShelf() - .withRequestExpiration(LocalDate.of(2024, 7, 30)) - .withHoldShelfExpiration(LocalDate.of(2024, 8, 15)) - .withPickupServicePointId(servicePointResource.getId())).getId().toString()).toList(); - } - - private void assertRequestDetails(JsonObject representation, String id, String barcodeName) { - assertThat(representation.getString("id"), is(id)); - assertThat(representation.getString("requestType"), is("Page")); - assertThat(representation.getString("requestLevel"), is("Item")); - assertThat(representation.getString("requestDate"), is("2017-07-15T09:35:27.000Z")); - assertThat(representation.getJsonObject("item").getString("barcode"), is(barcodeName)); - assertThat(representation.getString("fulfillmentPreference"), is("Hold Shelf")); - assertThat(representation.getString("requestExpirationDate"), is("2024-07-30T23:59:59.000Z")); - assertThat(representation.getString("holdShelfExpirationDate"), is("2024-08-15")); - assertThat(representation.getString("status"), is("Open - Not yet filled")); - assertThat(representation.getString("pickupServicePointId"), is(servicePointResource.getId().toString())); - } - - private void assertPrintDetails(JsonObject representation, int count, String printEventDate) { - var printDetailObject = representation.getJsonObject("printDetails"); - var lastPrintRequesterObject = printDetailObject.getJsonObject("lastPrintRequester"); - assertThat(printDetailObject.getInteger("count"), is(count)); - assertThat(printDetailObject.getString("lastPrintedDate"), is(printEventDate)); - assertThat(lastPrintRequesterObject.getString("middleName"), - is(userResource.getJson().getJsonObject("personal").getString("middleName"))); - assertThat(lastPrintRequesterObject.getString("lastName"), - is(userResource.getJson().getJsonObject("personal").getString("lastName"))); - assertThat(lastPrintRequesterObject.getString("firstName"), - is(userResource.getJson().getJsonObject("personal").getString("firstName"))); + .withPickupServicePointId(pickupServicePointId)).getId()).toList(); } } diff --git a/src/test/java/api/requests/RequestsAPICreationTests.java b/src/test/java/api/requests/RequestsAPICreationTests.java index 0595792bd6..24a3bc3a9d 100644 --- a/src/test/java/api/requests/RequestsAPICreationTests.java +++ b/src/test/java/api/requests/RequestsAPICreationTests.java @@ -16,6 +16,7 @@ import static api.support.fixtures.TemplateContextMatchers.getUserContextMatchers; import static api.support.http.CqlQuery.exactMatch; import static api.support.http.CqlQuery.notEqual; +import static api.support.http.InterfaceUrls.printEventsUrl; import static api.support.http.Limit.limit; import static api.support.http.Offset.noOffset; import static api.support.matchers.EventMatchers.isValidLoanDueDateChangedEvent; @@ -107,6 +108,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import api.support.builders.CirculationSettingBuilder; import org.apache.http.HttpStatus; import org.awaitility.Awaitility; import org.folio.circulation.domain.ItemStatus; @@ -194,6 +196,7 @@ public class RequestsAPICreationTests extends APITests { public void afterEach() { mockClockManagerToReturnDefaultDateTime(); configurationsFixture.deleteTlrFeatureConfig(); + circulationSettingsClient.deleteAll(); } @Test @@ -4859,6 +4862,123 @@ void createHoldRequestForDcbItemAndResponseContainsDcbTitle() { } + @Test + void fetchRequestWithOutPrintEventFeature() { + assertThat("Circulation settings enabled", circulationSettingsClient.getAll().isEmpty()); + var barcode1 = "barcode1"; + var barcode2 = "barcode2"; + // creating 2 different requests and assert request details without enabling printEvent feature + var userResource = usersFixture.charlotte(); + var servicePointId = servicePointsFixture.cd1().getId(); + var requestId1 = createRequest(userResource, barcode1, servicePointId).getId(); + var requestId2 = createRequest(userResource, barcode2, servicePointId).getId(); + + JsonObject requestRepresentation1 = requestsClient.getMany(exactMatch("id", requestId1.toString())).getFirst(); + JsonObject requestRepresentation2 = requestsClient.getMany(exactMatch("id", requestId2.toString())).getFirst(); + assertRequestDetails(requestRepresentation1, requestId1, barcode1, servicePointId); + assertRequestDetails(requestRepresentation2, requestId2, barcode2, servicePointId); + assertThat("printDetails should be null for request1 because the print event feature is not enabled", + requestRepresentation1.getJsonObject("printDetails"), Matchers.nullValue()); + assertThat("printDetails should be null for request2 because the print event feature is not enabled", + requestRepresentation2.getJsonObject("printDetails"), Matchers.nullValue()); + } + + @Test + void printAndFetchDetailWithPrintEventFeatureEnabled() { + assertThat("Circulation settings enabled", circulationSettingsClient.getAll().isEmpty()); + var barcode1 = "barcode1"; + var barcode2 = "barcode2"; + // creating 2 different requests and print those 2 requests + // assert request details with enabling printEvent feature + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("printEventLogFeature") + .withValue(new JsonObject().put("enablePrintLog", true))); + var userResource1 = usersFixture.charlotte(); + var userResource2 = usersFixture.jessica(); + var servicePointId = servicePointsFixture.cd1().getId(); + var requestId1 = createRequest(userResource1, barcode1, servicePointId).getId(); + var requestId2 = createRequest(userResource2, barcode2, servicePointId).getId(); + // Printing request1 using user1 and assertRequest details + var printRequest = getPrintEvent(); + printRequest.put("requestIds", List.of(requestId1)); + printRequest.put("requesterId", userResource1.getId()); + + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + + // Printing request2 using user2 and assertRequest details + printRequest = getPrintEvent(); + printRequest.put("requestIds", List.of(requestId2)); + printRequest.put("requesterId", userResource2.getId()); + + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + JsonObject requestRepresentation1 = requestsClient.getMany(exactMatch("id", requestId1.toString())).getFirst(); + JsonObject requestRepresentation2 = requestsClient.getMany(exactMatch("id", requestId2.toString())).getFirst(); + assertRequestDetails(requestRepresentation1, requestId1, barcode1, servicePointId); + assertRequestDetails(requestRepresentation2, requestId2, barcode2, servicePointId); + assertThat("printDetails should not be null for request1 as the feature is enabled and the request is printed", + requestRepresentation1.getJsonObject("printDetails"), Matchers.notNullValue()); + assertThat("printDetails should not be null for request2 as the feature is enabled and the request is printed", + requestRepresentation2.getJsonObject("printDetails"), Matchers.notNullValue()); + assertPrintDetails(requestRepresentation1, 1, "2024-06-25T11:54:07.000Z", userResource1); + assertPrintDetails(requestRepresentation2, 1, "2024-06-25T11:54:07.000Z", userResource2); + + // printing both request for second time using user2 and assert requestDetails + printRequest.put("printEventDate", "2024-06-25T12:54:07.000Z"); + printRequest.put("requestIds", List.of(requestId1, requestId2)); + printRequest.put("requesterId", userResource2.getId()); + + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + + requestRepresentation1 = requestsClient.getMany(exactMatch("id", requestId1.toString())).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", requestId2.toString())).getFirst(); + assertRequestDetails(requestRepresentation1, requestId1, barcode1, servicePointId); + assertRequestDetails(requestRepresentation2, requestId2, barcode2, servicePointId); + assertPrintDetails(requestRepresentation1, 2, "2024-06-25T12:54:07.000Z", userResource2); + assertPrintDetails(requestRepresentation2, 2, "2024-06-25T12:54:07.000Z", userResource2); + + // printing request1 for third time using user1 and assert requestDetails + printRequest.put("printEventDate", "2024-06-25T12:58:07.000Z"); + printRequest.put("requestIds", List.of(requestId1)); + printRequest.put("requesterId", userResource1.getId()); + + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + + requestRepresentation1 = requestsClient.getMany(exactMatch("id", requestId1.toString())).getFirst(); + requestRepresentation2 = requestsClient.getMany(exactMatch("id", requestId2.toString())).getFirst(); + assertRequestDetails(requestRepresentation1, requestId1, barcode1, servicePointId); + assertRequestDetails(requestRepresentation2, requestId2, barcode2, servicePointId); + assertPrintDetails(requestRepresentation1, 3, "2024-06-25T12:58:07.000Z", userResource1); + assertPrintDetails(requestRepresentation2, 2, "2024-06-25T12:54:07.000Z", userResource2); + } + + @Test + void printAndFetchRequestWithPrintEventFeatureDisabled() { + assertThat("Circulation settings enabled", circulationSettingsClient.getAll().isEmpty()); + var barcode1 = "barcode1"; + var barcode2 = "barcode2"; + // creating 2 different requests and print it + // assert request details without enabling printEvent feature + circulationSettingsClient.create(new CirculationSettingBuilder() + .withName("printEventLogFeature") + .withValue(new JsonObject().put("enablePrintLog", false))); + var userResource = usersFixture.charlotte(); + var servicePointId = servicePointsFixture.cd1().getId(); + var requestId1 = createRequest(userResource, barcode1, servicePointId).getId(); + var requestId2 = createRequest(userResource, barcode2, servicePointId).getId(); + var printRequest = getPrintEvent(); + printRequest.put("requestIds", List.of(requestId1, requestId2)); + + restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); + + JsonObject requestRepresentation1 = requestsClient.getMany(exactMatch("id", requestId1.toString())).getFirst(); + JsonObject requestRepresentation2 = requestsClient.getMany(exactMatch("id", requestId2.toString())).getFirst(); + assertRequestDetails(requestRepresentation1, requestId1, barcode1, servicePointId); + assertRequestDetails(requestRepresentation2, requestId2, barcode2, servicePointId); + assertThat("printDetails should be null for request1 because the print event feature is disabled", + requestRepresentation1.getJsonObject("printDetails"), Matchers.nullValue()); + assertThat("printDetails should be null for request2 because the print event feature is disabled", + requestRepresentation2.getJsonObject("printDetails"), Matchers.nullValue()); + } private void setUpNoticesForTitleLevelRequests(boolean isNoticeEnabledInTlrSettings, boolean isNoticeEnabledInNoticePolicy) { @@ -5190,4 +5310,52 @@ private void validateInstanceRepresentation(JsonObject requestInstance) { assertThat(firstPublication.getString("place"), is("New York")); assertThat(firstPublication.getString("dateOfPublication"), is("2016")); } + + private IndividualResource createRequest(UserResource userResource, String itemBarcode, + UUID pickupServicePointId) { + return requestsFixture.place( + new RequestBuilder() + .open() + .page() + .forItem(itemsFixture.basedUponSmallAngryPlanet(itemBarcode)) + .by(userResource) + .fulfillToHoldShelf() + .withRequestExpiration(LocalDate.of(2024, 7, 30)) + .withHoldShelfExpiration(LocalDate.of(2024, 8, 15)) + .withPickupServicePointId(pickupServicePointId)); + } + + private void assertRequestDetails(JsonObject representation, UUID id, String barcodeName, UUID servicePointId) { + assertThat(representation.getString("id"), is(id.toString())); + assertThat(representation.getString("requestType"), is("Page")); + assertThat(representation.getString("requestLevel"), is("Item")); + assertThat(representation.getString("requestDate"), is("2017-07-15T09:35:27.000Z")); + assertThat(representation.getJsonObject("item").getString("barcode"), is(barcodeName)); + assertThat(representation.getString("fulfillmentPreference"), is("Hold Shelf")); + assertThat(representation.getString("requestExpirationDate"), is("2024-07-30T23:59:59.000Z")); + assertThat(representation.getString("holdShelfExpirationDate"), is("2024-08-15")); + assertThat(representation.getString("status"), is("Open - Not yet filled")); + assertThat(representation.getString("pickupServicePointId"), is(servicePointId.toString())); + } + + private JsonObject getPrintEvent() { + return new JsonObject() + .put("requesterId", "5f5751b4-e352-4121-adca-204b0c2aec43") + .put("requesterName", "requester") + .put("printEventDate", "2024-06-25T11:54:07.000Z"); + } + + private void assertPrintDetails(JsonObject representation, int count, String printEventDate, + UserResource userResource) { + var printDetailObject = representation.getJsonObject("printDetails"); + var lastPrintRequesterObject = printDetailObject.getJsonObject("lastPrintRequester"); + assertThat(printDetailObject.getInteger("count"), is(count)); + assertThat(printDetailObject.getString("lastPrintedDate"), is(printEventDate)); + assertThat(lastPrintRequesterObject.getString("middleName"), + is(userResource.getJson().getJsonObject("personal").getString("middleName"))); + assertThat(lastPrintRequesterObject.getString("lastName"), + is(userResource.getJson().getJsonObject("personal").getString("lastName"))); + assertThat(lastPrintRequesterObject.getString("firstName"), + is(userResource.getJson().getJsonObject("personal").getString("firstName"))); + } } diff --git a/src/test/java/api/support/fakes/FakePrintEventStatusModule.java b/src/test/java/api/support/fakes/FakePrintEventStatusModule.java index 628fb2203c..aaeced3434 100644 --- a/src/test/java/api/support/fakes/FakePrintEventStatusModule.java +++ b/src/test/java/api/support/fakes/FakePrintEventStatusModule.java @@ -25,7 +25,6 @@ public class FakePrintEventStatusModule { public void register(Router router) { router.post("/print-events-storage/print-events-status") .handler(this::handlePrintEventStatusRequest); - } private void handlePrintEventStatusRequest(RoutingContext routingContext) { @@ -33,51 +32,52 @@ private void handlePrintEventStatusRequest(RoutingContext routingContext) { var requestIds = request.getJsonArray("requestIds"); if (requestIds.isEmpty()) { Buffer buffer = Buffer.buffer( - "Size must be 1", "UTF-8"); + "size must be between 1 and 2147483647", "UTF-8"); routingContext.response() .setStatusCode(HTTP_UNPROCESSABLE_ENTITY.toInt()) .putHeader("content-type", "text/plain; charset=utf-8") .putHeader("content-length", Integer.toString(buffer.length())) .write(buffer); routingContext.response().end(); + } else { + var jsonObjectList = new ArrayList<>(getStorage() + .getTenantResources("/print-events-storage/print-events-entry", getTenantId()) + .values() + .stream() + .toList()); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"); + // Sorting jsonObjectList based on PrintEventDate so that it will always return latest printEventDetail + jsonObjectList.sort((obj1, obj2) -> { + try { + Date date1 = dateFormat.parse(obj1.getString("printEventDate")); + Date date2 = dateFormat.parse(obj2.getString("printEventDate")); + return date2.compareTo(date1); + } catch (ParseException e) { + throw new RuntimeException(e); + } + }); + Map> groupByRequestIdMap = new LinkedHashMap<>(); + requestIds.forEach(requestId -> { + var requestList = jsonObjectList.stream().filter(jsonObject -> + jsonObject.getJsonArray("requestIds").contains(requestId)) + .toList(); + groupByRequestIdMap.put((String) requestId, requestList); + }); + var jsonObjectResponse = new JsonObject(); + var printEventStatusResponses = new ArrayList<>(); + jsonObjectResponse.put("printEventsStatusResponses", printEventStatusResponses); + requestIds.forEach(id -> { + var requestDetail = groupByRequestIdMap.get(id); + if (requestDetail != null && !requestDetail.isEmpty()) { + var object = new JsonObject() + .put("requestId", id) + .put("count", requestDetail.size()) + .put("requesterId", requestDetail.get(0).getString("requesterId")) + .put("printEventDate", requestDetail.get(0).getString("printEventDate")); + printEventStatusResponses.add(object); + } + }); + ok(jsonObjectResponse).writeTo(routingContext.response()); } - var jsonObjectList = new ArrayList<>(getStorage() - .getTenantResources("/print-events-storage/print-events-entry", getTenantId()) - .values() - .stream() - .toList()); - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"); - // Sorting jsonObjectList based on PrintEventDate so that it will always return latest printEventDetail - jsonObjectList.sort((obj1, obj2) -> { - try { - Date date1 = dateFormat.parse(obj1.getString("printEventDate")); - Date date2 = dateFormat.parse(obj2.getString("printEventDate")); - return date2.compareTo(date1); - } catch (ParseException e) { - throw new RuntimeException(e); - } - }); - Map> groupByRequestIdMap = new LinkedHashMap<>(); - requestIds.forEach(requestId -> { - var requestList = jsonObjectList.stream().filter(jsonObject -> - jsonObject.getJsonArray("requestIds").contains(requestId)) - .toList(); - groupByRequestIdMap.put((String) requestId, requestList); - }); - var jsonObjectResponse = new JsonObject(); - var printEventStatusResponses = new ArrayList<>(); - jsonObjectResponse.put("printEventsStatusResponses", printEventStatusResponses); - requestIds.forEach(id -> { - var requestDetail = groupByRequestIdMap.get(id); - if (requestDetail != null && !requestDetail.isEmpty()) { - var object = new JsonObject() - .put("requestId", id) - .put("count", requestDetail.size()) - .put("requesterId", requestDetail.get(0).getString("requesterId")) - .put("printEventDate", requestDetail.get(0).getString("printEventDate")); - printEventStatusResponses.add(object); - } - }); - ok(jsonObjectResponse).writeTo(routingContext.response()); } } From 422ec7001209d627ed7aa283d5ac83c5fd853ad7 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Tue, 30 Jul 2024 13:57:38 +0530 Subject: [PATCH 34/38] CIRC-2100 Fixing sonar issue --- .../org/folio/circulation/domain/RequestRepresentation.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index df5811fa0a..a284f70dbf 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -261,8 +261,9 @@ private static void removeSearchIndexFields(JsonObject request) { private static void addPrintEventProperties(JsonObject request, PrintEventDetail printEventDetail) { if (printEventDetail == null) { - String msg = "addPrintEventProperties:: printEvent property is null for requestId {}"; - log.info(msg, request.getString("id")); + if(log.isInfoEnabled()) { + log.info("addPrintEventProperties:: printEvent property is null for requestId {}", request.getString("id")); + } return; } From fe2a97def513b7d66673346aace2408ef491e3bb Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Tue, 30 Jul 2024 13:58:39 +0530 Subject: [PATCH 35/38] CIRC-2100 code formatting --- .../org/folio/circulation/domain/RequestRepresentation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java index a284f70dbf..6a51004c10 100644 --- a/src/main/java/org/folio/circulation/domain/RequestRepresentation.java +++ b/src/main/java/org/folio/circulation/domain/RequestRepresentation.java @@ -261,7 +261,7 @@ private static void removeSearchIndexFields(JsonObject request) { private static void addPrintEventProperties(JsonObject request, PrintEventDetail printEventDetail) { if (printEventDetail == null) { - if(log.isInfoEnabled()) { + if (log.isInfoEnabled()) { log.info("addPrintEventProperties:: printEvent property is null for requestId {}", request.getString("id")); } return; From e3644c8e59663091b128646a19fced6ad74c7008 Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Tue, 30 Jul 2024 17:04:35 +0530 Subject: [PATCH 36/38] CIRC-2100 Adding loggers --- .../storage/PrintEventsRepository.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index d6264ae9d5..28ba455866 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -53,9 +53,15 @@ public CompletableFuture>> findPrintEventDetails log.debug("findPrintEventDetails:: parameters multipleRequests: {}", () -> multipleRecordsAsString(multipleRequests)); return validatePrintEventFeatureFlag() - .thenCompose(isEnabled -> Boolean.TRUE.equals(isEnabled) ? - fetchAndMapPrintEventDetails(multipleRequests) - : completedFuture(succeeded(multipleRequests))); + .thenCompose(isEnabled -> { + if (Boolean.TRUE.equals(isEnabled)) { + log.info("findPrintEventDetails:: printEvent feature is enabled for the tenant"); + return fetchAndMapPrintEventDetails(multipleRequests); + } else { + log.info("findPrintEventDetails:: printEvent feature is disabled for the tenant"); + return completedFuture(succeeded(multipleRequests)); + } + }); } private CompletableFuture>> fetchAndMapPrintEventDetails( @@ -64,6 +70,7 @@ private CompletableFuture>> fetchAndMapPrintEven () -> multipleRecordsAsString(multipleRequests)); var requestIds = multipleRequests.toKeys(Request::getId); if (requestIds.isEmpty()) { + log.info("fetchAndMapPrintEventDetails:: No request id found"); return completedFuture(succeeded(multipleRequests)); } return fetchPrintDetailsByRequestIds(requestIds) From 140a354f21a77287240b902d43b007ea83a8fa2d Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 31 Jul 2024 20:00:45 +0530 Subject: [PATCH 37/38] CIRC-2100 Return 204 for post api and fixing test cases --- .../org/folio/circulation/resources/PrintEventsResource.java | 5 +++-- src/test/java/api/printEvents/PrintEventsTests.java | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index 72ba78fcd1..605919b60b 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -13,7 +13,7 @@ import org.folio.circulation.infrastructure.storage.requests.RequestRepository; import org.folio.circulation.support.Clients; import org.folio.circulation.support.RouteRegistration; -import org.folio.circulation.support.http.server.JsonHttpResponse; +import org.folio.circulation.support.http.server.NoContentResponse; import org.folio.circulation.support.http.server.WebContext; import org.folio.circulation.support.results.Result; @@ -24,6 +24,7 @@ import static org.folio.circulation.support.ValidationErrorFailure.singleValidationError; import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; +import static org.folio.circulation.support.results.MappingFunctions.toFixedValue; import static org.folio.circulation.support.results.Result.ofAsync; import static org.folio.circulation.support.results.Result.succeeded; @@ -61,7 +62,7 @@ void create(RoutingContext routingContext) { .thenCompose(r -> r.after(validatePrintEventFeatureFlag(circulationSettingsRepository))) .thenCompose(r -> r.after(validateRequests(requestRepository))) .thenCompose(r -> r.after(printEventsRepository::create)) - .thenApply(r -> r.map(response -> JsonHttpResponse.created(null, null))) + .thenApply(r -> r.map(toFixedValue(NoContentResponse::noContent))) .thenAccept(context::writeResultToHttpResponse); } diff --git a/src/test/java/api/printEvents/PrintEventsTests.java b/src/test/java/api/printEvents/PrintEventsTests.java index 4459ad504c..17e4b5d9c3 100644 --- a/src/test/java/api/printEvents/PrintEventsTests.java +++ b/src/test/java/api/printEvents/PrintEventsTests.java @@ -14,7 +14,7 @@ import static api.support.http.InterfaceUrls.printEventsUrl; import static api.support.matchers.ResponseStatusCodeMatcher.hasStatus; -import static org.folio.HttpStatus.HTTP_CREATED; +import static org.folio.HttpStatus.HTTP_NO_CONTENT; import static org.folio.HttpStatus.HTTP_UNPROCESSABLE_ENTITY; import static org.hamcrest.MatcherAssert.assertThat; @@ -29,7 +29,7 @@ void postPrintEventsTest() { JsonObject printRequest = getPrintEvent(); printRequest.put("requestIds", createOneHundredRequests()); Response response = restAssuredClient.post(printRequest, printEventsUrl("/print-events-entry"), "post-print-event"); - assertThat(response, hasStatus(HTTP_CREATED)); + assertThat(response, hasStatus(HTTP_NO_CONTENT)); } @Test From ba38f05da6ee89ed8e1195228380f034ebf436bb Mon Sep 17 00:00:00 2001 From: Vignesh-Kalyanasundaram Date: Wed, 31 Jul 2024 20:34:47 +0530 Subject: [PATCH 38/38] CIRC-2100 Changes made as per the review comments and refactoring code --- .../storage/PrintEventsRepository.java | 45 +++++++++---------- .../resources/PrintEventsResource.java | 4 +- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java index 28ba455866..8622357131 100644 --- a/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java +++ b/src/main/java/org/folio/circulation/infrastructure/storage/PrintEventsRepository.java @@ -16,9 +16,12 @@ import java.util.Collection; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.CompletableFuture; import static java.util.concurrent.CompletableFuture.completedFuture; +import static org.folio.circulation.resources.PrintEventsResource.PRINT_EVENT_FLAG_PROPERTY_NAME; +import static org.folio.circulation.resources.PrintEventsResource.PRINT_EVENT_FLAG_QUERY; import static org.folio.circulation.support.http.ResponseMapping.forwardOnFailure; import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty; import static org.folio.circulation.support.results.Result.of; @@ -28,7 +31,8 @@ public class PrintEventsRepository { private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - + private static final String RECORDS_PROPERTY_NAME = "printEventsStatusResponses"; + private static final String REQUEST_IDS = "requestIds"; private final CollectionResourceClient printEventsStorageClient; private final CollectionResourceClient printEventsStorageStatusClient; private final CirculationSettingsRepository circulationSettingsRepository; @@ -52,27 +56,21 @@ public CompletableFuture>> findPrintEventDetails MultipleRecords multipleRequests) { log.debug("findPrintEventDetails:: parameters multipleRequests: {}", () -> multipleRecordsAsString(multipleRequests)); - return validatePrintEventFeatureFlag() - .thenCompose(isEnabled -> { - if (Boolean.TRUE.equals(isEnabled)) { - log.info("findPrintEventDetails:: printEvent feature is enabled for the tenant"); - return fetchAndMapPrintEventDetails(multipleRequests); - } else { - log.info("findPrintEventDetails:: printEvent feature is disabled for the tenant"); - return completedFuture(succeeded(multipleRequests)); - } - }); - } - - private CompletableFuture>> fetchAndMapPrintEventDetails( - MultipleRecords multipleRequests) { - log.debug("fetchAndMapPrintEventDetails:: parameters multipleRequests: {}", - () -> multipleRecordsAsString(multipleRequests)); var requestIds = multipleRequests.toKeys(Request::getId); if (requestIds.isEmpty()) { log.info("fetchAndMapPrintEventDetails:: No request id found"); return completedFuture(succeeded(multipleRequests)); } + return validatePrintEventFeatureFlag() + .thenCompose(isEnabled -> Boolean.TRUE.equals(isEnabled) + ? fetchAndMapPrintEventDetails(multipleRequests, requestIds) + : completedFuture(succeeded(multipleRequests))); + } + + private CompletableFuture>> fetchAndMapPrintEventDetails( + MultipleRecords multipleRequests, Set requestIds) { + log.debug("fetchAndMapPrintEventDetails:: parameters multipleRequests: {}, requestIds {}", + () -> multipleRecordsAsString(multipleRequests), () -> requestIds); return fetchPrintDetailsByRequestIds(requestIds) .thenApply(printEventRecordsResult -> printEventRecordsResult .next(printEventRecords -> mapPrintEventDetailsToRequest(printEventRecords, multipleRequests))); @@ -80,21 +78,19 @@ private CompletableFuture>> fetchAndMapPrintEven private CompletableFuture validatePrintEventFeatureFlag() { log.debug("validatePrintEventFeatureFlag:: Fetching and validating enablePrintLog flag from settings"); - return circulationSettingsRepository.findBy("query=name=printEventLogFeature") + return circulationSettingsRepository.findBy(PRINT_EVENT_FLAG_QUERY) .thenApply(res -> Optional.ofNullable(res.value()) - .map(records -> records.getRecords().stream() - .map(setting -> Boolean.valueOf(getProperty(setting.getValue(), "enablePrintLog"))) - .findFirst() - .orElse(false)) + .flatMap(records -> records.getRecords().stream().findFirst()) + .map(setting -> Boolean.valueOf(getProperty(setting.getValue(), PRINT_EVENT_FLAG_PROPERTY_NAME))) .orElse(false)); } private CompletableFuture>> fetchPrintDetailsByRequestIds (Collection requestIds) { log.debug("fetchPrintDetailsByRequestIds:: fetching print event details for requestIds {}", requestIds); - return printEventsStorageStatusClient.post(new JsonObject().put("requestIds", requestIds)) + return printEventsStorageStatusClient.post(new JsonObject().put(REQUEST_IDS, requestIds)) .thenApply(flatMapResult(response -> - MultipleRecords.from(response, PrintEventDetail::from, "printEventsStatusResponses"))); + MultipleRecords.from(response, PrintEventDetail::from, RECORDS_PROPERTY_NAME))); } private Result> mapPrintEventDetailsToRequest( @@ -106,5 +102,4 @@ private Result> mapPrintEventDetailsToRequest( requests.mapRecords(request -> request .withPrintEventDetail(printEventDetailMap.getOrDefault(request.getId(), null)))); } - } diff --git a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java index 605919b60b..b530e20110 100644 --- a/src/main/java/org/folio/circulation/resources/PrintEventsResource.java +++ b/src/main/java/org/folio/circulation/resources/PrintEventsResource.java @@ -30,11 +30,11 @@ public class PrintEventsResource extends Resource { private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - private static final String PRINT_EVENT_FLAG_QUERY = "query=name=printEventLogFeature"; + public static final String PRINT_EVENT_FLAG_QUERY = "query=name=printEventLogFeature"; private static final String PRINT_EVENT_FEATURE_DISABLED_ERROR = "print event feature is disabled for this tenant"; private static final String NO_CONFIG_FOUND_ERROR = "No configuration found for print event feature"; private static final String MULTIPLE_CONFIGS_ERROR = "Multiple configurations found for print event feature"; - private static final String PRINT_EVENT_FLAG_PROPERTY_NAME = "enablePrintLog"; + public static final String PRINT_EVENT_FLAG_PROPERTY_NAME = "enablePrintLog"; public PrintEventsResource(HttpClient client) { super(client);