Skip to content

Commit 2ade190

Browse files
Circstore-513 Implementing post print Event API (#469)
* CIRCSTORE-513 implementing post print Event Api including test cases
1 parent 65cef7f commit 2ade190

File tree

12 files changed

+291
-2
lines changed

12 files changed

+291
-2
lines changed

descriptors/ModuleDescriptor-template.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,21 @@
645645
}
646646
]
647647
},
648+
{
649+
"id": "print-events-storage",
650+
"version": "1.0",
651+
"handlers": [
652+
{
653+
"methods": [
654+
"POST"
655+
],
656+
"pathPattern": "/print-events-storage/print-events-entry",
657+
"permissionsRequired": [
658+
"print-events-storage.print-events-entry.item.post"
659+
]
660+
}
661+
]
662+
},
648663
{
649664
"id": "_timer",
650665
"version": "1.0",
@@ -677,6 +692,11 @@
677692
}
678693
],
679694
"permissionSets": [
695+
{
696+
"permissionName": "print-events-storage.print-events-entry.item.post",
697+
"displayName": "print events storage - save print event logs",
698+
"description": "save print event log in storage"
699+
},
680700
{
681701
"permissionName": "check-in-storage.check-ins.collection.get",
682702
"displayName": "Check-in storage - get check-ins collection",
@@ -1133,7 +1153,8 @@
11331153
"circulation-storage.circulation-settings.item.get",
11341154
"circulation-storage.circulation-settings.item.post",
11351155
"circulation-storage.circulation-settings.item.put",
1136-
"circulation-storage.circulation-settings.item.delete"
1156+
"circulation-storage.circulation-settings.item.delete",
1157+
"print-events-storage.print-events-entry.item.post"
11371158
]
11381159
},
11391160
{
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"requestIds": [
3+
"059e54bb-53e5-4039-a2fb-b34358e88b0a",
4+
"e70dcbae-30c6-47ac-94f8-4ffefd44a935"
5+
],
6+
"requesterId": "d51470ea-5daa-480b-a4aa-09c8c6d9940e",
7+
"requesterName": "requester",
8+
"printEventDate": "2024-06-25T20:00:00+05:30"
9+
}

ramls/print-events-request.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"description": "Print Events Request",
4+
"type": "object",
5+
"properties": {
6+
"requestIds": {
7+
"description": "List of request IDs",
8+
"type": "array",
9+
"minItems": 1,
10+
"items": {
11+
"type": "string",
12+
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[1-5][a-fA-F0-9]{3}-[89abAB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$"
13+
}
14+
},
15+
"requesterId": {
16+
"description": "ID of the requester",
17+
"type": "string",
18+
"$ref": "raml-util/schemas/uuid.schema",
19+
"pattern": "^(?!\\s*$).+"
20+
},
21+
"requesterName": {
22+
"description": "Name of the requester",
23+
"type": "string",
24+
"pattern": "^(?!\\s*$).+"
25+
},
26+
"printEventDate": {
27+
"description": "Date and time when the print command is executed",
28+
"type": "string",
29+
"format": "date-time"
30+
}
31+
},
32+
"required": [
33+
"requestIds",
34+
"requesterId",
35+
"requesterName",
36+
"printEventDate"
37+
]
38+
}

ramls/print-events-storage.raml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#%RAML 1.0
2+
title: Print Events Storage
3+
version: v1.0
4+
protocols: [ HTTP, HTTPS ]
5+
baseUri: http://localhost:9130
6+
7+
documentation:
8+
- title: Print Events Storage API
9+
content: <b>Storage for print events</b>
10+
11+
types:
12+
print-events-request: !include print-events-request.json
13+
errors: !include raml-util/schemas/errors.schema
14+
15+
traits:
16+
validate: !include raml-util/traits/validation.raml
17+
18+
/print-events-storage:
19+
/print-events-entry:
20+
post:
21+
is: [validate]
22+
description: save a print event log
23+
body:
24+
application/json:
25+
type: print-events-request
26+
responses:
27+
201:
28+
description: "All items have been successfully created or updated"
29+
409:
30+
description: "Optimistic locking version conflict"
31+
body:
32+
text/plain:
33+
example: "Version error"
34+
413:
35+
description: "Payload too large"
36+
body:
37+
text/plain:
38+
example: "Payload too large"
39+
422:
40+
description: "Unprocessable entity"
41+
body:
42+
application/json:
43+
type: errors
44+
500:
45+
description: "Internal server error"
46+
body:
47+
text/plain:
48+
example: "Internal server error"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.folio.rest.impl;
2+
3+
import io.vertx.core.AsyncResult;
4+
import io.vertx.core.Context;
5+
import io.vertx.core.Handler;
6+
import org.folio.rest.jaxrs.model.PrintEventsRequest;
7+
import org.folio.rest.jaxrs.resource.PrintEventsStorage;
8+
import org.folio.service.PrintEventsService;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
import javax.ws.rs.core.Response;
13+
import java.util.Map;
14+
15+
import static io.vertx.core.Future.succeededFuture;
16+
17+
public class PrintEventsApi implements PrintEventsStorage {
18+
private static final Logger LOG = LoggerFactory.getLogger(PrintEventsApi.class);
19+
20+
@Override
21+
public void postPrintEventsStoragePrintEventsEntry(PrintEventsRequest printEventsRequest, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
22+
LOG.info("postPrintEventsStoragePrintEvents:: save print events {}", printEventsRequest);
23+
new PrintEventsService(vertxContext, okapiHeaders)
24+
.create(printEventsRequest)
25+
.onSuccess(response -> asyncResultHandler.handle(succeededFuture(response)))
26+
.onFailure(throwable -> asyncResultHandler.handle(succeededFuture(PostPrintEventsStoragePrintEventsEntryResponse.respond500WithTextPlain(throwable.getMessage()))));
27+
}
28+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.folio.rest.model;
2+
3+
import lombok.Data;
4+
import org.folio.rest.jaxrs.model.Metadata;
5+
import java.util.Date;
6+
7+
@Data
8+
public class PrintEvent {
9+
private String id;
10+
private String requestId;
11+
private String requesterId;
12+
private String requesterName;
13+
private Date printEventDate;
14+
private Metadata metadata;
15+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.folio.service;
2+
3+
import io.vertx.core.Context;
4+
import io.vertx.core.Future;
5+
import org.folio.rest.jaxrs.model.PrintEventsRequest;
6+
import org.folio.rest.jaxrs.resource.PrintEventsStorage;
7+
import org.folio.rest.model.PrintEvent;
8+
import org.folio.rest.persist.PgUtil;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
import javax.ws.rs.core.Response;
13+
import java.util.List;
14+
import java.util.Map;
15+
16+
import static org.folio.support.ModuleConstants.PRINT_EVENTS_TABLE;
17+
18+
public class PrintEventsService {
19+
20+
private static final Logger LOG = LoggerFactory.getLogger(PrintEventsService.class);
21+
private static final int MAX_ENTITIES = 10000;
22+
private final Context vertxContext;
23+
private final Map<String, String> okapiHeaders;
24+
25+
26+
public PrintEventsService(Context vertxContext, Map<String, String> okapiHeaders) {
27+
this.vertxContext = vertxContext;
28+
this.okapiHeaders = okapiHeaders;
29+
}
30+
31+
public Future<Response> create(PrintEventsRequest printEventRequest) {
32+
LOG.info("create:: save print events {}", printEventRequest);
33+
List<PrintEvent> printEvents = printEventRequest.getRequestIds().stream().map(requestId -> {
34+
PrintEvent event = new PrintEvent();
35+
event.setRequestId(requestId);
36+
event.setRequesterId(printEventRequest.getRequesterId());
37+
event.setRequesterName(printEventRequest.getRequesterName());
38+
event.setPrintEventDate(printEventRequest.getPrintEventDate());
39+
return event;
40+
}).toList();
41+
return PgUtil.postSync(PRINT_EVENTS_TABLE, printEvents, MAX_ENTITIES, false, okapiHeaders, vertxContext,
42+
PrintEventsStorage.PostPrintEventsStoragePrintEventsEntryResponse.class);
43+
}
44+
}

src/main/java/org/folio/support/ModuleConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class ModuleConstants {
2929
TlrFeatureToggleJob.class;
3030
public static final String REQUEST_POLICY_TABLE = "request_policy";
3131
public static final Class<RequestPolicy> REQUEST_POLICY_CLASS = RequestPolicy.class;
32+
public static final String PRINT_EVENTS_TABLE = "print_events";
3233

3334
private ModuleConstants(){
3435
}

src/main/resources/templates/db_scripts/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,11 @@
525525
"removeAccents": true
526526
}
527527
]
528+
},
529+
{
530+
"tableName": "print_events",
531+
"withMetadata": true,
532+
"withAuditing": false
528533
}
529534
],
530535
"scripts": [
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.folio.rest.api;
2+
3+
import io.vertx.core.json.JsonObject;
4+
import org.folio.rest.support.ApiTests;
5+
import org.folio.rest.support.JsonResponse;
6+
import org.folio.rest.support.ResponseHandler;
7+
import org.junit.Test;
8+
9+
import java.net.MalformedURLException;
10+
import java.util.List;
11+
import java.util.concurrent.CompletableFuture;
12+
import java.util.concurrent.ExecutionException;
13+
14+
import static org.folio.rest.support.http.InterfaceUrls.printEventsUrl;
15+
import static org.folio.rest.support.matchers.HttpResponseStatusCodeMatchers.isCreated;
16+
import static org.folio.rest.support.matchers.HttpResponseStatusCodeMatchers.isUnprocessableEntity;
17+
import static org.hamcrest.junit.MatcherAssert.assertThat;
18+
19+
public class PrintEventsAPITest extends ApiTests {
20+
21+
@Test
22+
public void canCreatePrintEventLog() throws MalformedURLException, ExecutionException, InterruptedException {
23+
JsonObject printEventsJson = getPrintEvent();
24+
final CompletableFuture<JsonResponse> postCompleted = new CompletableFuture<>();
25+
client.post(printEventsUrl("/print-events-entry"), printEventsJson, StorageTestSuite.TENANT_ID,
26+
ResponseHandler.json(postCompleted));
27+
final JsonResponse postResponse = postCompleted.get();
28+
assertThat(postResponse, isCreated());
29+
}
30+
31+
@Test
32+
public void createPrintEventLogWithMissingFields() throws MalformedURLException, ExecutionException, InterruptedException {
33+
List<String> requestIds = List.of("5f5751b4-e352-4121-adca-204b0c2aec43", "5f5751b4-e352-4121-adca-204b0c2aec44");
34+
JsonObject printEventsJson = new JsonObject()
35+
.put("requestIds", requestIds)
36+
.put("requesterName", "Sample Requester")
37+
.put("printEventDate", "2024-06-25T14:30:00Z");
38+
final CompletableFuture<JsonResponse> postCompleted = new CompletableFuture<>();
39+
client.post(printEventsUrl("/print-events-entry"), printEventsJson, StorageTestSuite.TENANT_ID,
40+
ResponseHandler.json(postCompleted));
41+
final JsonResponse postResponse = postCompleted.get();
42+
assertThat(postResponse, isUnprocessableEntity());
43+
}
44+
45+
@Test
46+
public void createPrintEventLogWithBlankFields() throws MalformedURLException, ExecutionException, InterruptedException {
47+
JsonObject printEventsJson = getPrintEvent();
48+
printEventsJson.put("requesterId", " ");
49+
final CompletableFuture<JsonResponse> postCompleted = new CompletableFuture<>();
50+
client.post(printEventsUrl("/print-events-entry"), printEventsJson, StorageTestSuite.TENANT_ID,
51+
ResponseHandler.json(postCompleted));
52+
final JsonResponse postResponse = postCompleted.get();
53+
assertThat(postResponse, isUnprocessableEntity());
54+
}
55+
56+
@Test
57+
public void createPrintEventLogWhenRequestListIsEmpty() throws MalformedURLException, ExecutionException, InterruptedException {
58+
List<String> requestIds = List.of();
59+
JsonObject printEventsJson = getPrintEvent();
60+
printEventsJson.put("requestIds", requestIds);
61+
final CompletableFuture<JsonResponse> postCompleted = new CompletableFuture<>();
62+
client.post(printEventsUrl("/print-events-entry"), printEventsJson, StorageTestSuite.TENANT_ID,
63+
ResponseHandler.json(postCompleted));
64+
final JsonResponse postResponse = postCompleted.get();
65+
assertThat(postResponse, isUnprocessableEntity());
66+
}
67+
68+
private JsonObject getPrintEvent() {
69+
List<String> requestIds = List.of("5f5751b4-e352-4121-adca-204b0c2aec43", "5f5751b4-e352-4121-adca-204b0c2aec44");
70+
return new JsonObject()
71+
.put("requestIds", requestIds)
72+
.put("requesterId", "5f5751b4-e352-4121-adca-204b0c2aec43")
73+
.put("requesterName", "requester")
74+
.put("printEventDate", "2024-06-25T14:30:00Z");
75+
}
76+
}

0 commit comments

Comments
 (0)