Skip to content

Commit

Permalink
CIRC-2138: added sync for request table post PrintEvent insertions (#487
Browse files Browse the repository at this point in the history
)

* CIRC-2138: added sync for request table post  PrintEvent insertions

* CIRC-2138: set additionalProperties false for request.printDetails

* CIRC-2138: fixed printed to isPrinted in printDetails in request sync query

* CIRC-2138: fixed sonar issues

* CIRC-2138: addded test case for 5XX case

* CIRC-2138: Bump up interface version
  • Loading branch information
kapil-epam authored Sep 25, 2024
1 parent 28aa0b7 commit 651d888
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 15 deletions.
2 changes: 1 addition & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
},
{
"id": "request-storage",
"version": "6.0",
"version": "6.1",
"handlers": [
{
"methods": ["GET"],
Expand Down
24 changes: 24 additions & 0 deletions ramls/request.json
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,30 @@
"description": "Tags",
"$ref": "raml-util/schemas/tags.schema"
},
"printDetails": {
"type": "object",
"description": "PrintDetails",
"properties": {
"printCount": {
"type": "integer",
"description": "Number of times print slip generated."
},
"requesterId": {
"type": "string",
"description": "UUID of print slip requester."
},
"isPrinted": {
"type": "boolean",
"description": "Whether print slip was printed in past."
},
"printEventDate": {
"type": "string",
"format": "date-time",
"description": "Date and time when print slip was generated last time."
}
},
"additionalProperties": false
},
"awaitingPickupRequestClosedDate": {
"description": "A date when the request with awaiting pickup status was closed",
"type": "string",
Expand Down
6 changes: 1 addition & 5 deletions src/main/java/org/folio/rest/impl/PrintEventsApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,14 @@
import javax.ws.rs.core.Response;
import java.util.Map;

import static io.vertx.core.Future.succeededFuture;

public class PrintEventsApi implements PrintEventsStorage {
private static final Logger LOG = LoggerFactory.getLogger(PrintEventsApi.class);

@Override
public void postPrintEventsStoragePrintEventsEntry(PrintEventsRequest printEventsRequest, Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
LOG.info("postPrintEventsStoragePrintEvents:: save print events {}", printEventsRequest);
new PrintEventsService(vertxContext, okapiHeaders)
.create(printEventsRequest)
.onSuccess(response -> asyncResultHandler.handle(succeededFuture(response)))
.onFailure(throwable -> asyncResultHandler.handle(succeededFuture(PostPrintEventsStoragePrintEventsEntryResponse.respond500WithTextPlain(throwable.getMessage()))));
.create(printEventsRequest, asyncResultHandler);
}

@Override
Expand Down
89 changes: 80 additions & 9 deletions src/main/java/org/folio/service/PrintEventsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import io.vertx.core.AsyncResult;
import io.vertx.core.Context;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.sqlclient.Row;
import io.vertx.sqlclient.RowSet;
Expand All @@ -14,28 +13,31 @@
import org.folio.rest.model.PrintEvent;
import org.folio.rest.persist.PgUtil;
import org.folio.rest.persist.PostgresClient;
import org.folio.rest.tools.utils.MetadataUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.core.Response;
import java.text.SimpleDateFormat;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.stream.Collectors;

import static io.vertx.core.Future.succeededFuture;
import static org.folio.rest.persist.PgUtil.postgresClient;
import static org.folio.rest.persist.PostgresClient.convertToPsqlStandard;
import static org.folio.support.ModuleConstants.PRINT_EVENTS_TABLE;
import static org.folio.support.ModuleConstants.REQUEST_TABLE;

public class PrintEventsService {

private static final Logger LOG = LoggerFactory.getLogger(PrintEventsService.class);
private static final int MAX_ENTITIES = 10000;
private final Context vertxContext;
private final Map<String, String> okapiHeaders;
private final PostgresClient postgresClient;

private static final String PRINT_EVENT_FETCH_QUERY = """
WITH cte AS (
Expand All @@ -53,31 +55,100 @@ ORDER BY (jsonb->>'printEventDate')::timestamptz DESC) AS rank
rank = 1;
""";

private static String requestPrintSyncQueryString = """
WITH print_counts AS (
SELECT
jsonb->>'requestId' AS request_id,
COUNT(*) AS print_count
FROM %s
WHERE jsonb->>'requestId' IN (%s)
GROUP BY jsonb->>'requestId'
)
UPDATE %s
SET jsonb =
(jsonb
|| jsonb_build_object(
'printDetails',
jsonb_build_object(
'printCount', print_counts.print_count,
'requesterId', %s,
'isPrinted', true,
'printEventDate', %s
)
)
)
FROM print_counts
WHERE id = print_counts.request_id::uuid;
""";



public PrintEventsService(Context vertxContext, Map<String, String> okapiHeaders) {
this.vertxContext = vertxContext;
this.okapiHeaders = okapiHeaders;
this.postgresClient = PgUtil.postgresClient(vertxContext, okapiHeaders);
}

public Future<Response> create(PrintEventsRequest printEventRequest) {
public void create(PrintEventsRequest printEventRequest,
Handler<AsyncResult<Response>> asyncResultHandler) {
LOG.info("create:: save print events {}", printEventRequest);
List<PrintEvent> printEvents = printEventRequest.getRequestIds().stream().map(requestId -> {
List<PrintEvent> printEvents =
printEventRequest.getRequestIds().stream().map(requestId -> {
PrintEvent event = new PrintEvent();
event.setRequestId(requestId);
event.setRequesterId(printEventRequest.getRequesterId());
event.setRequesterName(printEventRequest.getRequesterName());
event.setPrintEventDate(printEventRequest.getPrintEventDate());
return event;
}).toList();
return PgUtil.postSync(PRINT_EVENTS_TABLE, printEvents, MAX_ENTITIES, false, okapiHeaders, vertxContext,
PrintEventsStorage.PostPrintEventsStoragePrintEventsEntryResponse.class);
try {
MetadataUtil.populateMetadata(printEvents, okapiHeaders);
} catch (Exception e) {
String msg =
"Cannot populate metadata of printEvents list elements: " + e.getMessage();
LOG.error(msg, e);
asyncResultHandler.handle(succeededFuture(PrintEventsStorage.PostPrintEventsStoragePrintEventsEntryResponse.respond500WithTextPlain(msg)));
return;
}

postgresClient.withTrans(conn -> conn.saveBatch(PRINT_EVENTS_TABLE,
printEvents)
.compose(printEventsResult -> conn.execute(
buildRequestSyncQuery(printEventRequest, okapiHeaders)
))).onFailure(handler ->
asyncResultHandler.handle(
succeededFuture(PrintEventsStorage.PostPrintEventsStoragePrintEventsEntryResponse.respond500WithTextPlain(handler.getMessage()))
)
).onSuccess(handler ->
asyncResultHandler.handle(
succeededFuture(PrintEventsStorage.PostPrintEventsStoragePrintEventsEntryResponse.respond201())
));
}

private String buildRequestSyncQuery(PrintEventsRequest printEventRequest,
Map<String, String> okapiHeaders) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
df.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));

String tenantId = okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT);
String printEventTableName =
convertToPsqlStandard(tenantId) + "." + PRINT_EVENTS_TABLE;
String requestTableName =
convertToPsqlStandard(tenantId) + "." + REQUEST_TABLE;
String requestIds = printEventRequest.getRequestIds().stream()
.map(requestId -> "'" + requestId + "'")
.collect(Collectors.joining(", "));
String requesterId = "'" + printEventRequest.getRequesterId() + "'";
String printEventDate =
"'" + df.format(printEventRequest.getPrintEventDate()) + "'";

return requestPrintSyncQueryString.formatted(printEventTableName,
requestIds, requestTableName, requesterId,
printEventDate);
}

public void getPrintEventRequestDetails(List<String> requestIds, Handler<AsyncResult<Response>> asyncResultHandler) {
LOG.debug("getPrintEventRequestDetails:: Fetching print event details for requestIds {}", requestIds);
String tenantId = okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT);
PostgresClient postgresClient = postgresClient(vertxContext, okapiHeaders);
postgresClient.execute(formatQuery(tenantId, requestIds), handler -> {
try {
if (handler.succeeded()) {
Expand Down
13 changes: 13 additions & 0 deletions src/test/java/org/folio/rest/api/PrintEventsAPITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import static org.folio.rest.support.http.InterfaceUrls.printEventsUrl;
import static org.folio.rest.support.matchers.HttpResponseStatusCodeMatchers.isCreated;
import static org.folio.rest.support.matchers.HttpResponseStatusCodeMatchers.isInternalServerError;
import static org.folio.rest.support.matchers.HttpResponseStatusCodeMatchers.isOk;
import static org.folio.rest.support.matchers.HttpResponseStatusCodeMatchers.isUnprocessableEntity;
import static org.hamcrest.core.Is.is;
Expand Down Expand Up @@ -180,6 +181,18 @@ public void getPrintEventStatusWithInvalidRequestIds() throws MalformedURLExcept
assertThat(jsonObject.getJsonArray("printEventsStatusResponses").size(), is(0));
}

@Test
public void createPrintEventLogAndValidate5XX() throws MalformedURLException,
ExecutionException, InterruptedException {
JsonObject printEventsJson = getPrintEvent();
final CompletableFuture<JsonResponse> postCompleted = new CompletableFuture<>();
client.post(printEventsUrl("/print-events-entry"), printEventsJson,
"INVALID_TENANT_ID",
ResponseHandler.json(postCompleted));
final JsonResponse postResponse = postCompleted.get();
assertThat(postResponse, isInternalServerError());
}

private JsonObject getPrintEvent() {
List<String> requestIds = List.of("5f5751b4-e352-4121-adca-204b0c2aec43", "5f5751b4-e352-4121-adca-204b0c2aec44");
return new JsonObject()
Expand Down

0 comments on commit 651d888

Please sign in to comment.