From c73fa3eca834b3770ce2c57f32288c4eb6d7532e Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Wed, 27 Mar 2024 10:50:12 +0500 Subject: [PATCH 01/35] updated acq-model for routing list --- ramls/acq-models | 2 +- ramls/routing-lists.raml | 48 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 ramls/routing-lists.raml diff --git a/ramls/acq-models b/ramls/acq-models index 0502772fd..a3385f315 160000 --- a/ramls/acq-models +++ b/ramls/acq-models @@ -1 +1 @@ -Subproject commit 0502772fdadd941734a132501c0cfe9baab243d8 +Subproject commit a3385f315835414e45422041ecb249ba7f2fc028 diff --git a/ramls/routing-lists.raml b/ramls/routing-lists.raml new file mode 100644 index 000000000..2f2aa02c1 --- /dev/null +++ b/ramls/routing-lists.raml @@ -0,0 +1,48 @@ +#%RAML 1.0 +title: "RoutingList" +baseUri: https://github.com/folio-org/mod-orders +version: v1.0 + +documentation: + - title: Routing lists + content: CRUD API to manage routing lists. + +types: + title: !include acq-models/mod-orders-storage/schemas/routing_list.json + title_collection: !include acq-models/mod-orders-storage/schemas/routing_list_collection.json + UUID: + type: string + pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$ + +traits: + pageable: !include raml-util/traits/pageable.raml + searchable: !include raml-util/traits/searchable.raml + +resourceTypes: + collection: !include raml-util/rtypes/collection.raml + collection-item: !include raml-util/rtypes/item-collection.raml + +/orders/routing-lists: + type: + collection: + exampleCollection: !include acq-models/mod-orders-storage/examples/routing_list_collection.sample + exampleItem: !include acq-models/mod-orders-storage/examples/routing_list_get.sample + schemaCollection: routing_list_collection + schemaItem: routing_list + get: + description: Get routing lists + is: [ + searchable: {description: "with valid searchable fields: for example routing list", example: "[\"routing_list\", \"ROUTING_LIST\", \"=\"]"}, + pageable + ] + /{id}/process-template: + uriParameters: + id: + description: The UUID of a Title + type: UUID + type: + collection-item: + exampleItem: !include acq-models/mod-orders-storage/examples/routing_list_get.sample + schema: routing_list + post: + description: Execute mod-template-engine to process templates with replaced token placeholders [update] From 47ef021f9cbb96b58643e026e53995a6d8b13ade Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 28 Mar 2024 15:35:14 +0500 Subject: [PATCH 02/35] [MODORSERS-1026] - Implement API to execute mod-template-engine request --- descriptors/ModuleDescriptor-template.json | 13 ++++ ramls/routing-lists.raml | 12 +-- .../template/TemplateProcessingRequest.java | 66 ++++++++++++++++ .../orders/utils/ResourcePathResolver.java | 6 ++ .../java/org/folio/rest/core/RestClient.java | 13 ++-- .../org/folio/rest/impl/RoutingListAPI.java | 39 ++++++++++ .../java/org/folio/service/UserService.java | 25 ++++++ .../routinglist/RoutingListService.java | 76 +++++++++++++++++++ .../java/org/folio/rest/impl/MockServer.java | 2 + .../routinglist/RoutingListServiceTest.java | 66 ++++++++++++++++ .../eee951de-ea49-400a-96e8-705ae5a1e1e8.json | 11 +++ .../mockdata/users/user_collection.json | 41 ++++++++++ 12 files changed, 355 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/folio/models/template/TemplateProcessingRequest.java create mode 100644 src/main/java/org/folio/rest/impl/RoutingListAPI.java create mode 100644 src/main/java/org/folio/service/routinglist/RoutingListService.java create mode 100644 src/test/java/org/folio/service/routinglist/RoutingListServiceTest.java create mode 100644 src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json create mode 100644 src/test/resources/mockdata/users/user_collection.json diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 194061617..e26debc38 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -1003,6 +1003,19 @@ } ] }, + { + "id": "orders.routing-list", + "version": "1.0", + "handlers": [ + { + "methods": ["POST"], + "pathPattern": "/orders/routing-lists/{id}/process-template", + "permissionsRequired": [ + "orders.routing-list.item.post" + ] + } + ] + }, { "id": "_jsonSchemas", "version": "1.0", diff --git a/ramls/routing-lists.raml b/ramls/routing-lists.raml index 2f2aa02c1..3593957bf 100644 --- a/ramls/routing-lists.raml +++ b/ramls/routing-lists.raml @@ -8,8 +8,8 @@ documentation: content: CRUD API to manage routing lists. types: - title: !include acq-models/mod-orders-storage/schemas/routing_list.json - title_collection: !include acq-models/mod-orders-storage/schemas/routing_list_collection.json + routing_list: !include acq-models/mod-orders-storage/schemas/routing_list.json + routing_list_collection: !include acq-models/mod-orders-storage/schemas/routing_list_collection.json UUID: type: string pattern: ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$ @@ -19,8 +19,8 @@ traits: searchable: !include raml-util/traits/searchable.raml resourceTypes: - collection: !include raml-util/rtypes/collection.raml - collection-item: !include raml-util/rtypes/item-collection.raml + collection: !include rtypes/collection-with-json-response.raml + collection-item: !include rtypes/item-collection-with-json-response.raml /orders/routing-lists: type: @@ -40,9 +40,5 @@ resourceTypes: id: description: The UUID of a Title type: UUID - type: - collection-item: - exampleItem: !include acq-models/mod-orders-storage/examples/routing_list_get.sample - schema: routing_list post: description: Execute mod-template-engine to process templates with replaced token placeholders [update] diff --git a/src/main/java/org/folio/models/template/TemplateProcessingRequest.java b/src/main/java/org/folio/models/template/TemplateProcessingRequest.java new file mode 100644 index 000000000..51dcd575f --- /dev/null +++ b/src/main/java/org/folio/models/template/TemplateProcessingRequest.java @@ -0,0 +1,66 @@ +package org.folio.models.template; + +import java.util.List; +import java.util.UUID; + +import lombok.Getter; + +@Getter +public class TemplateProcessingRequest { + private UUID templateId; + private String lang; + private String outputFormat; + private Context context; + + public TemplateProcessingRequest withTemplateId(UUID templateId) { + this.templateId = templateId; + return this; + } + + public TemplateProcessingRequest withLang(String lang) { + this.lang = lang; + return this; + } + + public TemplateProcessingRequest withOutputFormat(String outputFormat) { + this.outputFormat = outputFormat; + return this; + } + + public TemplateProcessingRequest withContext(Context context) { + this.context = context; + return this; + } + + @Getter + public static class Context { + private List users; + private List items; + + public Context withUsers(List users) { + this.users = users; + return this; + } + + } + + @Getter + public static class User { + private String name; + public User withName(String name) { + this.name = name; + return this; + } + } + + @Getter + public static class Item { + private String name; + + public Item setName(String name) { + this.name = name; + return this; + } + } +} + diff --git a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java index 50b3da277..c03ffcdfc 100644 --- a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java +++ b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java @@ -28,6 +28,9 @@ private ResourcePathResolver() { public static final String PAYMENT_STATUS = "paymentStatus"; public static final String ORDER_TEMPLATES = "orderTemplates"; public static final String TITLES = "titles"; + public static final String ROUTING_LISTS = "routing-lists"; + public static final String TEMPLATE_REQUEST = "template-request"; + public static final String USERS = "users"; public static final String FUNDS = "finance.funds"; public static final String BUDGETS = "finance.budgets"; public static final String LEDGERS = "finance.ledgers"; @@ -66,6 +69,8 @@ private ResourcePathResolver() { apis.put(RECEIVING_HISTORY, "/orders-storage/receiving-history"); apis.put(PO_LINE_NUMBER, "/orders-storage/po-line-number"); apis.put(ORDER_TEMPLATES, "/orders-storage/order-templates"); + apis.put(ROUTING_LISTS, "/orders-storage/routing-lists"); + apis.put(TEMPLATE_REQUEST, "/template-request"); apis.put(FUNDS, "/finance/funds"); apis.put(BUDGETS, "/finance/budgets"); apis.put(LEDGERS, "/finance-storage/ledgers"); @@ -86,6 +91,7 @@ private ResourcePathResolver() { apis.put(ORDER_INVOICE_RELATIONSHIP, "/orders-storage/order-invoice-relns"); apis.put(EXPORT_HISTORY, "/orders-storage/export-history"); apis.put(TAGS, "/tags"); + apis.put(USERS, "/users"); SUB_OBJECT_COLLECTION_APIS = Collections.unmodifiableMap(apis); SUB_OBJECT_ITEM_APIS = Collections.unmodifiableMap( diff --git a/src/main/java/org/folio/rest/core/RestClient.java b/src/main/java/org/folio/rest/core/RestClient.java index 17a787c98..14d846ca5 100644 --- a/src/main/java/org/folio/rest/core/RestClient.java +++ b/src/main/java/org/folio/rest/core/RestClient.java @@ -10,13 +10,6 @@ import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.folio.okapi.common.WebClientFactory; -import org.folio.rest.core.exceptions.HttpException; -import org.folio.rest.core.models.RequestContext; -import org.folio.rest.core.models.RequestEntry; - import io.vertx.core.Context; import io.vertx.core.Future; import io.vertx.core.MultiMap; @@ -29,6 +22,12 @@ import io.vertx.ext.web.client.WebClientOptions; import io.vertx.ext.web.client.predicate.ErrorConverter; import io.vertx.ext.web.client.predicate.ResponsePredicate; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.folio.okapi.common.WebClientFactory; +import org.folio.rest.core.exceptions.HttpException; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.core.models.RequestEntry; public class RestClient { diff --git a/src/main/java/org/folio/rest/impl/RoutingListAPI.java b/src/main/java/org/folio/rest/impl/RoutingListAPI.java new file mode 100644 index 000000000..145bf7234 --- /dev/null +++ b/src/main/java/org/folio/rest/impl/RoutingListAPI.java @@ -0,0 +1,39 @@ +package org.folio.rest.impl; + +import javax.ws.rs.core.Response; +import java.util.Map; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Context; +import io.vertx.core.Handler; +import org.apache.commons.lang.NotImplementedException; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.jaxrs.model.RoutingList; +import org.folio.rest.jaxrs.resource.OrdersRoutingLists; +import org.folio.service.routinglist.RoutingListService; +import org.springframework.beans.factory.annotation.Autowired; + +public class RoutingListAPI extends BaseApi implements OrdersRoutingLists { + + @Autowired + private RoutingListService routingListService; + + @Override + public void getOrdersRoutingLists(String query, String totalRecords, int offset, int limit, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + throw new NotImplementedException(); + } + + @Override + public void postOrdersRoutingLists(RoutingList entity, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + throw new NotImplementedException(); + } + + @Override + public void postOrdersRoutingListsProcessTemplateById(String id, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + routingListService.processTemplateEngine(id, new RequestContext(vertxContext, okapiHeaders)) + .onFailure(t -> handleErrorResponse(asyncResultHandler, t)); + } +} diff --git a/src/main/java/org/folio/service/UserService.java b/src/main/java/org/folio/service/UserService.java index d19d99f65..017c8e355 100644 --- a/src/main/java/org/folio/service/UserService.java +++ b/src/main/java/org/folio/service/UserService.java @@ -1,12 +1,37 @@ package org.folio.service; +import static org.folio.orders.utils.HelperUtils.convertIdsToCqlQuery; +import static org.folio.orders.utils.ResourcePathResolver.USERS; +import static org.folio.orders.utils.ResourcePathResolver.resourcesPath; import static org.folio.rest.RestVerticle.OKAPI_USERID_HEADER; +import java.util.List; import java.util.Map; +import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; +import org.folio.rest.core.RestClient; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.core.models.RequestEntry; + public class UserService { + private static final String ENDPOINT = resourcesPath(USERS); + private final RestClient restClient; + + public UserService(RestClient restClient) { + this.restClient = restClient; + } public static String getCurrentUserId(Map okapiHeaders) { return okapiHeaders.get(OKAPI_USERID_HEADER); } + + public Future getUsersByIds(List userIds, RequestContext requestContext) { + var requestEntry = new RequestEntry(USERS) + .withOffset(0) + .withLimit(Integer.MAX_VALUE) + .withQuery(convertIdsToCqlQuery(userIds, "sourceInvoiceId")); + + return restClient.get(requestEntry, JsonObject.class, requestContext); + } } diff --git a/src/main/java/org/folio/service/routinglist/RoutingListService.java b/src/main/java/org/folio/service/routinglist/RoutingListService.java new file mode 100644 index 000000000..c6e10fd29 --- /dev/null +++ b/src/main/java/org/folio/service/routinglist/RoutingListService.java @@ -0,0 +1,76 @@ +package org.folio.service.routinglist; + +import static org.folio.orders.utils.ResourcePathResolver.ROUTING_LISTS; +import static org.folio.orders.utils.ResourcePathResolver.TEMPLATE_REQUEST; +import static org.folio.orders.utils.ResourcePathResolver.resourcesPath; + +import java.util.List; +import java.util.UUID; + +import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; +import lombok.extern.log4j.Log4j2; +import org.folio.models.template.TemplateProcessingRequest; +import org.folio.rest.core.RestClient; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.core.models.RequestEntry; +import org.folio.rest.jaxrs.model.RoutingList; +import org.folio.service.UserService; + +@Log4j2 +public class RoutingListService { + + private static final String ENDPOINT = resourcesPath(ROUTING_LISTS); + private static final String BY_ID_ENDPOINT = ENDPOINT + "/{id}"; + private final RestClient restClient; + private final UserService userService; + + public RoutingListService(RestClient restClient, UserService userService) { + this.restClient = restClient; + this.userService = userService; + } + + public Future processTemplateEngine(String id, RequestContext requestContext) { + return getRoutingListById(id, requestContext) + .compose(routingList -> fetchUsersAndCreateTemplate(routingList, requestContext)) + .compose(templateProcessingRequest -> postTemplateRequest(templateProcessingRequest, requestContext)); + } + + public Future getRoutingListById(String routingListId, RequestContext requestContext) { + var requestEntry = new RequestEntry(BY_ID_ENDPOINT).withId(routingListId); + return restClient.get(requestEntry, RoutingList.class, requestContext); + } + + private Future fetchUsersAndCreateTemplate(RoutingList routingList, RequestContext requestContext) { + return userService.getUsersByIds(routingList.getUserIds(), requestContext) + .map(users -> createTemplateRequest(routingList, users)); + } + + private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, JsonObject users) { + var templateRequest =createBaseTemplateRequest(); + var userListForContext = createUserListForContext(users); + var context = new TemplateProcessingRequest.Context().withUsers(userListForContext); + templateRequest.withContext(context); + return templateRequest; + } + + private TemplateProcessingRequest createBaseTemplateRequest() { + return new TemplateProcessingRequest() + .withTemplateId(UUID.randomUUID()) + .withLang("en") + .withOutputFormat("text/plain"); + } + + private List createUserListForContext(JsonObject users) { + return users.getJsonArray("users").stream() + .map(JsonObject.class::cast) + .map(user -> new TemplateProcessingRequest.User() + .withName(user.getJsonObject("personal").getString("firstName")) + ) + .toList(); + } + + private Future postTemplateRequest(TemplateProcessingRequest templateProcessingRequest, RequestContext requestContext) { + return restClient.post(TEMPLATE_REQUEST, JsonObject.mapFrom(templateProcessingRequest), JsonObject.class, requestContext); + } +} diff --git a/src/test/java/org/folio/rest/impl/MockServer.java b/src/test/java/org/folio/rest/impl/MockServer.java index 58626f43a..dc4c9220b 100644 --- a/src/test/java/org/folio/rest/impl/MockServer.java +++ b/src/test/java/org/folio/rest/impl/MockServer.java @@ -242,6 +242,8 @@ public class MockServer { private static final String HOLDINGS_SOURCE_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "holdingsSources/"; public static final String PIECE_RECORDS_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "pieces/"; public static final String PO_LINES_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "lines/"; + public static final String ROUTING_LIST_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "routingLists/"; + public static final String USERS_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "users/"; public static final String TITLES_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "titles/"; private static final String ACQUISITIONS_UNITS_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "acquisitionsUnits/units"; private static final String ORDER_TEMPLATES_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "orderTemplates/"; diff --git a/src/test/java/org/folio/service/routinglist/RoutingListServiceTest.java b/src/test/java/org/folio/service/routinglist/RoutingListServiceTest.java new file mode 100644 index 000000000..23b620f77 --- /dev/null +++ b/src/test/java/org/folio/service/routinglist/RoutingListServiceTest.java @@ -0,0 +1,66 @@ +package org.folio.service.routinglist; + +import static io.vertx.core.Future.succeededFuture; +import static org.folio.TestUtils.getMockData; +import static org.folio.rest.impl.MockServer.ROUTING_LIST_MOCK_DATA_PATH; +import static org.folio.rest.impl.MockServer.USERS_MOCK_DATA_PATH; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; + +import java.io.IOException; + +import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; +import io.vertx.junit5.VertxExtension; +import io.vertx.junit5.VertxTestContext; +import org.folio.rest.core.RestClient; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.core.models.RequestEntry; +import org.folio.rest.jaxrs.model.RoutingList; +import org.folio.service.UserService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@ExtendWith(VertxExtension.class) +public class RoutingListServiceTest { + + private static final String ROUTING_LIST_ID = "eee951de-ea49-400a-96e8-705ae5a1e1e8"; + @InjectMocks + RoutingListService routingListService; + @Mock + private RestClient restClient; + @Mock + private UserService userService; + @Mock + private RequestContext requestContextMock; + + @BeforeEach + public void initMocks() { + MockitoAnnotations.openMocks(this); + } + + @Test + void processTemplate(VertxTestContext vertxTestContext) throws IOException { + var routingList = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + ".json")).mapTo(RoutingList.class); + var users = new JsonObject(getMockData(USERS_MOCK_DATA_PATH + "user_collection.json")); + + doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any(RequestContext.class)); + doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any(RequestContext.class)); + doReturn(succeededFuture(new JsonObject())).when(restClient).post(anyString(), any(), eq(JsonObject.class), any()); + + Future future = routingListService.processTemplateEngine(ROUTING_LIST_ID, requestContextMock); + + vertxTestContext.assertComplete(future) + .onComplete(result -> { + Assertions.assertTrue(result.succeeded()); + vertxTestContext.completeNow(); + }); + } +} diff --git a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json new file mode 100644 index 000000000..d89742eb8 --- /dev/null +++ b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json @@ -0,0 +1,11 @@ +{ + "id": "c0d13648-347b-4ac9-8c2f-5bc47248b87e", + "_version": 1, + "name": "Mars expedition", + "notes": "Future note", + "userIds": [ + "d926d900-e27d-46d6-bba8-31e9d5c2cf44", + "077274ad-6b4f-4c28-9779-6d381e7a1ca1" + ], + "poLineId": "8343e5a0-fed8-11e8-8eb2-f2801f1b9fd1" +} diff --git a/src/test/resources/mockdata/users/user_collection.json b/src/test/resources/mockdata/users/user_collection.json new file mode 100644 index 000000000..2473888ff --- /dev/null +++ b/src/test/resources/mockdata/users/user_collection.json @@ -0,0 +1,41 @@ +{ + "users": [ + { + "username": "mockuser8", + "id": "d926d900-e27d-46d6-bba8-31e9d5c2cf44", + "active": true, + "type": "staff", + "meta": { + "creation_date": "2016-11-05T0723", + "last_login_date": "" + }, + "personal": { + "firstName": "Albert", + "lastName": "Einstein", + "email": "albert@si.edu", + "phone": "927-306-2327" + } + }, + { + "username": "mockuser9", + "id": "077274ad-6b4f-4c28-9779-6d381e7a1ca1", + "active": true, + "type": "staff", + "meta": { + "creation_date": "2016-11-05T0723", + "last_login_date": "" + }, + "personal": { + "lastName": "Mockerson", + "middleName": "M.", + "firstName": "Mickey", + "email": "mock@biglibrary.org", + "phone": "2125551212", + "mobilePhone": "112233" + }, + "externalSystemId": "123", + "barcode": "test123" + } + ], + "totalRecords": 2 +} From 9661f92cbdbfe4ce5d141b9671bbc3851d1eb285 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 28 Mar 2024 16:10:20 +0500 Subject: [PATCH 03/35] [MODORSERS-1026] - Update permissions --- descriptors/ModuleDescriptor-template.json | 9 +++++++-- .../folio/service/routinglist/RoutingListService.java | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index e26debc38..3857c2b45 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -1723,6 +1723,11 @@ "displayName" : "orders holding-summary get", "description" : "Holding summary" }, + { + "permissionName": "orders.routing-list.item.post", + "displayName" : "orders routing-list item post", + "description" : "Orders routing-list item post" + }, { "permissionName": "orders.all", "displayName": "orders - all permissions", @@ -1757,8 +1762,8 @@ "orders.rollover.item.post", "orders.holding-summary.collection.get", "orders.acquisition-methods.all", - "orders.export-history.all" - + "orders.export-history.all", + "orders.routing-list.item.post" ] }, { diff --git a/src/main/java/org/folio/service/routinglist/RoutingListService.java b/src/main/java/org/folio/service/routinglist/RoutingListService.java index c6e10fd29..52e2bf5da 100644 --- a/src/main/java/org/folio/service/routinglist/RoutingListService.java +++ b/src/main/java/org/folio/service/routinglist/RoutingListService.java @@ -47,7 +47,7 @@ private Future fetchUsersAndCreateTemplate(RoutingLis } private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, JsonObject users) { - var templateRequest =createBaseTemplateRequest(); + var templateRequest = createBaseTemplateRequest(); var userListForContext = createUserListForContext(users); var context = new TemplateProcessingRequest.Context().withUsers(userListForContext); templateRequest.withContext(context); From 63766bcd9e3b7990453d73248cfd872174caade6 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 28 Mar 2024 16:29:27 +0500 Subject: [PATCH 04/35] [MODORSERS-1026] - Fixed context issue --- .../models/{template => }/TemplateProcessingRequest.java | 2 +- src/main/java/org/folio/rest/impl/RoutingListAPI.java | 6 ++++++ .../org/folio/service/routinglist/RoutingListService.java | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) rename src/main/java/org/folio/models/{template => }/TemplateProcessingRequest.java (97%) diff --git a/src/main/java/org/folio/models/template/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java similarity index 97% rename from src/main/java/org/folio/models/template/TemplateProcessingRequest.java rename to src/main/java/org/folio/models/TemplateProcessingRequest.java index 51dcd575f..ef01972dd 100644 --- a/src/main/java/org/folio/models/template/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -1,4 +1,4 @@ -package org.folio.models.template; +package org.folio.models; import java.util.List; import java.util.UUID; diff --git a/src/main/java/org/folio/rest/impl/RoutingListAPI.java b/src/main/java/org/folio/rest/impl/RoutingListAPI.java index 145bf7234..e834e5692 100644 --- a/src/main/java/org/folio/rest/impl/RoutingListAPI.java +++ b/src/main/java/org/folio/rest/impl/RoutingListAPI.java @@ -6,11 +6,13 @@ import io.vertx.core.AsyncResult; import io.vertx.core.Context; import io.vertx.core.Handler; +import io.vertx.core.Vertx; import org.apache.commons.lang.NotImplementedException; import org.folio.rest.core.models.RequestContext; import org.folio.rest.jaxrs.model.RoutingList; import org.folio.rest.jaxrs.resource.OrdersRoutingLists; import org.folio.service.routinglist.RoutingListService; +import org.folio.spring.SpringContextUtil; import org.springframework.beans.factory.annotation.Autowired; public class RoutingListAPI extends BaseApi implements OrdersRoutingLists { @@ -18,6 +20,10 @@ public class RoutingListAPI extends BaseApi implements OrdersRoutingLists { @Autowired private RoutingListService routingListService; + public RoutingListAPI() { + SpringContextUtil.autowireDependencies(this, Vertx.currentContext()); + } + @Override public void getOrdersRoutingLists(String query, String totalRecords, int offset, int limit, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { diff --git a/src/main/java/org/folio/service/routinglist/RoutingListService.java b/src/main/java/org/folio/service/routinglist/RoutingListService.java index 52e2bf5da..99ab848d6 100644 --- a/src/main/java/org/folio/service/routinglist/RoutingListService.java +++ b/src/main/java/org/folio/service/routinglist/RoutingListService.java @@ -10,7 +10,7 @@ import io.vertx.core.Future; import io.vertx.core.json.JsonObject; import lombok.extern.log4j.Log4j2; -import org.folio.models.template.TemplateProcessingRequest; +import org.folio.models.TemplateProcessingRequest; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; From 75c4c08f7e8ac44f856a4c2cb60a3a4615079480 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 28 Mar 2024 17:06:38 +0500 Subject: [PATCH 05/35] [MODORSERS-1026] - Added RoutingList service to ApplicationConfig --- src/main/java/org/folio/config/ApplicationConfig.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/folio/config/ApplicationConfig.java b/src/main/java/org/folio/config/ApplicationConfig.java index 584837b4b..6d1e885ec 100644 --- a/src/main/java/org/folio/config/ApplicationConfig.java +++ b/src/main/java/org/folio/config/ApplicationConfig.java @@ -26,6 +26,7 @@ import org.folio.service.ReasonForClosureService; import org.folio.service.SuffixService; import org.folio.service.TagService; +import org.folio.service.UserService; import org.folio.service.caches.ConfigurationEntriesCache; import org.folio.service.caches.InventoryCache; import org.folio.service.configuration.ConfigurationEntriesService; @@ -111,6 +112,7 @@ import org.folio.service.pieces.flows.update.PieceUpdateFlowInventoryManager; import org.folio.service.pieces.flows.update.PieceUpdateFlowManager; import org.folio.service.pieces.flows.update.PieceUpdateFlowPoLineService; +import org.folio.service.routinglist.RoutingListService; import org.folio.service.titles.TitleValidationService; import org.folio.service.titles.TitlesService; import org.springframework.beans.factory.annotation.Qualifier; @@ -434,6 +436,11 @@ CompositeOrderDynamicDataPopulateService combinedPopulateService(CompositeOrderR return new CombinedOrderDataPopulateService(compositeOrderRetrieveHolderBuilder, populateServices); } + @Bean + RoutingListService routingListService(RestClient restClient, UserService userService) { + return new RoutingListService(restClient, userService); + } + @Bean TitlesService titlesService(RestClient restClient, ProtectionService protectionService, InventoryManager inventoryManager) { return new TitlesService(restClient, protectionService, inventoryManager); From 5326d4e481e7e0d913af01911d3475bb57a43e1a Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 28 Mar 2024 17:34:22 +0500 Subject: [PATCH 06/35] [MODORSERS-1026] - Added UserService to ApplicationConfig --- src/main/java/org/folio/config/ApplicationConfig.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/folio/config/ApplicationConfig.java b/src/main/java/org/folio/config/ApplicationConfig.java index 6d1e885ec..0dab116a6 100644 --- a/src/main/java/org/folio/config/ApplicationConfig.java +++ b/src/main/java/org/folio/config/ApplicationConfig.java @@ -441,6 +441,11 @@ RoutingListService routingListService(RestClient restClient, UserService userSer return new RoutingListService(restClient, userService); } + @Bean + UserService userService(RestClient restClient) { + return new UserService(restClient); + } + @Bean TitlesService titlesService(RestClient restClient, ProtectionService protectionService, InventoryManager inventoryManager) { return new TitlesService(restClient, protectionService, inventoryManager); From 127644537735dc6cf7441fa0924b3651d1b1c450 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Fri, 29 Mar 2024 13:40:58 +0500 Subject: [PATCH 07/35] [MODORSERS-1026] - Implemented api to execute template-request api --- .../org/folio/config/ApplicationConfig.java | 6 +++--- .../orders/utils/ResourcePathResolver.java | 6 ++++-- ...RoutingListAPI.java => RoutingListsAPI.java} | 10 +++++----- ...istService.java => RoutingListsService.java} | 13 +++++++------ .../java/org/folio/service/UserService.java | 6 +++--- src/test/java/org/folio/ApiTestSuite.java | 5 +++++ src/test/java/org/folio/TestConstants.java | 5 +++++ .../java/org/folio/rest/impl/TitlesApiTest.java | 17 +++++++---------- ...ceTest.java => RoutingListsServiceTest.java} | 11 +++++------ 9 files changed, 44 insertions(+), 35 deletions(-) rename src/main/java/org/folio/rest/impl/{RoutingListAPI.java => RoutingListsAPI.java} (82%) rename src/main/java/org/folio/service/{routinglist/RoutingListService.java => RoutingListsService.java} (83%) rename src/test/java/org/folio/service/{routinglist/RoutingListServiceTest.java => RoutingListsServiceTest.java} (86%) diff --git a/src/main/java/org/folio/config/ApplicationConfig.java b/src/main/java/org/folio/config/ApplicationConfig.java index 0dab116a6..52c05c36b 100644 --- a/src/main/java/org/folio/config/ApplicationConfig.java +++ b/src/main/java/org/folio/config/ApplicationConfig.java @@ -112,7 +112,7 @@ import org.folio.service.pieces.flows.update.PieceUpdateFlowInventoryManager; import org.folio.service.pieces.flows.update.PieceUpdateFlowManager; import org.folio.service.pieces.flows.update.PieceUpdateFlowPoLineService; -import org.folio.service.routinglist.RoutingListService; +import org.folio.service.RoutingListsService; import org.folio.service.titles.TitleValidationService; import org.folio.service.titles.TitlesService; import org.springframework.beans.factory.annotation.Qualifier; @@ -437,8 +437,8 @@ CompositeOrderDynamicDataPopulateService combinedPopulateService(CompositeOrderR } @Bean - RoutingListService routingListService(RestClient restClient, UserService userService) { - return new RoutingListService(restClient, userService); + RoutingListsService routingListService(RestClient restClient, UserService userService) { + return new RoutingListsService(restClient, userService); } @Bean diff --git a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java index c03ffcdfc..fbc72ccdf 100644 --- a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java +++ b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java @@ -28,8 +28,9 @@ private ResourcePathResolver() { public static final String PAYMENT_STATUS = "paymentStatus"; public static final String ORDER_TEMPLATES = "orderTemplates"; public static final String TITLES = "titles"; - public static final String ROUTING_LISTS = "routing-lists"; - public static final String TEMPLATE_REQUEST = "template-request"; + public static final String ROUTING_LISTS = "routingLists"; + public static final String TEMPLATE_REQUEST = "templateRequest"; + public static final String PROCESS_TEMPLATE = "processTemplate"; public static final String USERS = "users"; public static final String FUNDS = "finance.funds"; public static final String BUDGETS = "finance.budgets"; @@ -71,6 +72,7 @@ private ResourcePathResolver() { apis.put(ORDER_TEMPLATES, "/orders-storage/order-templates"); apis.put(ROUTING_LISTS, "/orders-storage/routing-lists"); apis.put(TEMPLATE_REQUEST, "/template-request"); + apis.put(PROCESS_TEMPLATE, "/process-template"); apis.put(FUNDS, "/finance/funds"); apis.put(BUDGETS, "/finance/budgets"); apis.put(LEDGERS, "/finance-storage/ledgers"); diff --git a/src/main/java/org/folio/rest/impl/RoutingListAPI.java b/src/main/java/org/folio/rest/impl/RoutingListsAPI.java similarity index 82% rename from src/main/java/org/folio/rest/impl/RoutingListAPI.java rename to src/main/java/org/folio/rest/impl/RoutingListsAPI.java index e834e5692..430bb79d3 100644 --- a/src/main/java/org/folio/rest/impl/RoutingListAPI.java +++ b/src/main/java/org/folio/rest/impl/RoutingListsAPI.java @@ -11,16 +11,16 @@ import org.folio.rest.core.models.RequestContext; import org.folio.rest.jaxrs.model.RoutingList; import org.folio.rest.jaxrs.resource.OrdersRoutingLists; -import org.folio.service.routinglist.RoutingListService; +import org.folio.service.RoutingListsService; import org.folio.spring.SpringContextUtil; import org.springframework.beans.factory.annotation.Autowired; -public class RoutingListAPI extends BaseApi implements OrdersRoutingLists { +public class RoutingListsAPI extends BaseApi implements OrdersRoutingLists { @Autowired - private RoutingListService routingListService; + private RoutingListsService routingListsService; - public RoutingListAPI() { + public RoutingListsAPI() { SpringContextUtil.autowireDependencies(this, Vertx.currentContext()); } @@ -39,7 +39,7 @@ public void postOrdersRoutingLists(RoutingList entity, Map okapi @Override public void postOrdersRoutingListsProcessTemplateById(String id, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - routingListService.processTemplateEngine(id, new RequestContext(vertxContext, okapiHeaders)) + routingListsService.processTemplateRequest(id, new RequestContext(vertxContext, okapiHeaders)) .onFailure(t -> handleErrorResponse(asyncResultHandler, t)); } } diff --git a/src/main/java/org/folio/service/routinglist/RoutingListService.java b/src/main/java/org/folio/service/RoutingListsService.java similarity index 83% rename from src/main/java/org/folio/service/routinglist/RoutingListService.java rename to src/main/java/org/folio/service/RoutingListsService.java index 99ab848d6..b6b064ebf 100644 --- a/src/main/java/org/folio/service/routinglist/RoutingListService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -1,4 +1,4 @@ -package org.folio.service.routinglist; +package org.folio.service; import static org.folio.orders.utils.ResourcePathResolver.ROUTING_LISTS; import static org.folio.orders.utils.ResourcePathResolver.TEMPLATE_REQUEST; @@ -15,23 +15,23 @@ import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; import org.folio.rest.jaxrs.model.RoutingList; -import org.folio.service.UserService; @Log4j2 -public class RoutingListService { +public class RoutingListsService { private static final String ENDPOINT = resourcesPath(ROUTING_LISTS); private static final String BY_ID_ENDPOINT = ENDPOINT + "/{id}"; private final RestClient restClient; private final UserService userService; - public RoutingListService(RestClient restClient, UserService userService) { + public RoutingListsService(RestClient restClient, UserService userService) { this.restClient = restClient; this.userService = userService; } - public Future processTemplateEngine(String id, RequestContext requestContext) { - return getRoutingListById(id, requestContext) + public Future processTemplateRequest(String routingListId, RequestContext requestContext) { + log.debug("processTemplateRequest: Tying to process template request for routingListId={}", routingListId); + return getRoutingListById(routingListId, requestContext) .compose(routingList -> fetchUsersAndCreateTemplate(routingList, requestContext)) .compose(templateProcessingRequest -> postTemplateRequest(templateProcessingRequest, requestContext)); } @@ -51,6 +51,7 @@ private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, var userListForContext = createUserListForContext(users); var context = new TemplateProcessingRequest.Context().withUsers(userListForContext); templateRequest.withContext(context); + log.info("createTemplateRequest:: TemplateProcessingRequest object created : {}", JsonObject.mapFrom(templateRequest).encodePrettily()); return templateRequest; } diff --git a/src/main/java/org/folio/service/UserService.java b/src/main/java/org/folio/service/UserService.java index 017c8e355..8b088d55b 100644 --- a/src/main/java/org/folio/service/UserService.java +++ b/src/main/java/org/folio/service/UserService.java @@ -15,7 +15,7 @@ import org.folio.rest.core.models.RequestEntry; public class UserService { - private static final String ENDPOINT = resourcesPath(USERS); + private static final String USERS_ENDPOINT = resourcesPath(USERS); private final RestClient restClient; public UserService(RestClient restClient) { @@ -27,10 +27,10 @@ public static String getCurrentUserId(Map okapiHeaders) { } public Future getUsersByIds(List userIds, RequestContext requestContext) { - var requestEntry = new RequestEntry(USERS) + var requestEntry = new RequestEntry(USERS_ENDPOINT) .withOffset(0) .withLimit(Integer.MAX_VALUE) - .withQuery(convertIdsToCqlQuery(userIds, "sourceInvoiceId")); + .withQuery(convertIdsToCqlQuery(userIds, "id")); return restClient.get(requestEntry, JsonObject.class, requestContext); } diff --git a/src/test/java/org/folio/ApiTestSuite.java b/src/test/java/org/folio/ApiTestSuite.java index aaa6890d9..9d83c7424 100644 --- a/src/test/java/org/folio/ApiTestSuite.java +++ b/src/test/java/org/folio/ApiTestSuite.java @@ -97,6 +97,7 @@ import org.folio.service.pieces.flows.update.PieceUpdateFlowManagerTest; import org.folio.service.pieces.flows.update.PieceUpdateFlowPoLineServiceTest; import org.folio.service.pieces.validators.PieceValidatorUtilTest; +import org.folio.service.RoutingListsServiceTest; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; @@ -470,4 +471,8 @@ class FiscalYearServiceTestNested extends FiscalYearServiceTest { @Nested class TagServiceTestNested extends TagServiceTest { } + + @Nested + class RoutingListsServiceTestNested extends RoutingListsServiceTest { + } } diff --git a/src/test/java/org/folio/TestConstants.java b/src/test/java/org/folio/TestConstants.java index 809f13c6e..8297479bd 100644 --- a/src/test/java/org/folio/TestConstants.java +++ b/src/test/java/org/folio/TestConstants.java @@ -1,5 +1,6 @@ package org.folio; +import static org.folio.orders.utils.PermissionsUtil.OKAPI_HEADER_PERMISSIONS; import static org.folio.rest.RestVerticle.OKAPI_HEADER_TENANT; import static org.folio.rest.RestVerticle.OKAPI_HEADER_TOKEN; import static org.folio.rest.RestVerticle.OKAPI_USERID_HEADER; @@ -9,6 +10,8 @@ import java.util.UUID; import io.restassured.http.Header; +import io.vertx.core.json.JsonArray; +import org.folio.orders.utils.AcqDesiredPermissions; public final class TestConstants { @@ -63,6 +66,7 @@ private TestConstants() {} public static final Header NON_EXIST_LOAN_TYPE_TENANT_HEADER = new Header(OKAPI_HEADER_TENANT, NON_EXIST_LOAN_TYPE_TENANT); public static final Header NON_EXIST_CONFIG_X_OKAPI_TENANT = new Header(OKAPI_HEADER_TENANT, "ordersimpltest"); public static final Header X_OKAPI_USER_ID = new Header(OKAPI_USERID_HEADER, "440c89e3-7f6c-578a-9ea8-310dad23605e"); + public static final Header ALL_DESIRED_ACQ_PERMISSIONS_HEADER = new Header(OKAPI_HEADER_PERMISSIONS, new JsonArray(AcqDesiredPermissions.getValuesExceptBypass()).encode()); public static final Header X_OKAPI_USER_ID_WITH_ACQ_UNITS = new Header(OKAPI_USERID_HEADER, USER_ID_ASSIGNED_TO_ACQ_UNITS); public static final Header X_OKAPI_TOKEN = new Header(OKAPI_HEADER_TOKEN, "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkaWt1X2FkbWluIiwidXNlcl9pZCI6ImJmZTI2MjM0LTMzNjktNTdhYS05ZjhhLWU2ZWVhY2M0YTgzYiIsImlhdCI6MTU4MzE1Nzg5OCwidGVuYW50IjoiZGlrdSJ9.Mk7u4KaCywSuYtBgCT44oGcVC0C8jUMY9KjsUnug48I"); public static final Header EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10 = new Header(OKAPI_HEADER_TENANT, "test_diku_limit_10"); @@ -85,4 +89,5 @@ private TestConstants() {} public static final String PIECE_PATH = BASE_MOCK_DATA_PATH + "pieces/"; public static final String TILES_PATH = BASE_MOCK_DATA_PATH + "titles/"; public static final String ID_FOR_TEMPLATE_NAME_ALREADY_EXISTS = "cd0619fb-a628-4d90-be41-df8943e97768"; + public static final String ROUTING_LIST_ID = "eee951de-ea49-400a-96e8-705ae5a1e1e8"; } diff --git a/src/test/java/org/folio/rest/impl/TitlesApiTest.java b/src/test/java/org/folio/rest/impl/TitlesApiTest.java index d5b7004b7..73dc5cf8d 100644 --- a/src/test/java/org/folio/rest/impl/TitlesApiTest.java +++ b/src/test/java/org/folio/rest/impl/TitlesApiTest.java @@ -10,6 +10,7 @@ import static org.folio.TestConfig.clearServiceInteractions; import static org.folio.TestConfig.initSpringContext; import static org.folio.TestConfig.isVerticleNotDeployed; +import static org.folio.TestConstants.ALL_DESIRED_ACQ_PERMISSIONS_HEADER; import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10; import static org.folio.TestConstants.ID_BAD_FORMAT; import static org.folio.TestConstants.ID_DOES_NOT_EXIST; @@ -20,7 +21,6 @@ import static org.folio.TestUtils.getMinimalContentCompositePoLine; import static org.folio.TestUtils.getMockAsJson; import static org.folio.TestUtils.getMockData; -import static org.folio.orders.utils.PermissionsUtil.OKAPI_HEADER_PERMISSIONS; import static org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE; import static org.folio.rest.core.exceptions.ErrorCodes.*; import static org.folio.rest.impl.MockServer.TITLES_MOCK_DATA_PATH; @@ -38,14 +38,12 @@ import java.util.concurrent.TimeoutException; import io.restassured.http.Header; -import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.folio.ApiTestSuite; import org.folio.HttpStatus; import org.folio.config.ApplicationConfig; -import org.folio.orders.utils.AcqDesiredPermissions; import org.folio.rest.acq.model.Title; import org.folio.rest.jaxrs.model.CompositePoLine; import org.folio.rest.jaxrs.model.Details; @@ -72,7 +70,6 @@ public class TitlesApiTest { public static final String SAMPLE_TITLE_ID = "9a665b22-9fe5-4c95-b4ee-837a5433c95d"; private final JsonObject titleJsonReqData = getMockAsJson(TITLES_MOCK_DATA_PATH + "title.json"); private final JsonObject packageTitleJsonReqData = getMockAsJson(TITLES_MOCK_DATA_PATH + "package_title.json"); - public static final Header ALL_DESIRED_PERMISSIONS_HEADER = new Header(OKAPI_HEADER_PERMISSIONS, new JsonArray(AcqDesiredPermissions.getValuesExceptBypass()).encode()); private static boolean runningOnOwn; @@ -121,7 +118,7 @@ void testPostTitle() { assertThat(postTitleRq.getId(), nullValue()); Title postTitleRs = verifyPostResponse(TITLES_ENDPOINT, JsonObject.mapFrom(postTitleRq).encode(), - prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID_WITH_ACQ_UNITS, ALL_DESIRED_PERMISSIONS_HEADER), APPLICATION_JSON, HttpStatus.HTTP_CREATED.toInt()).as(Title.class); + prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID_WITH_ACQ_UNITS, ALL_DESIRED_ACQ_PERMISSIONS_HEADER), APPLICATION_JSON, HttpStatus.HTTP_CREATED.toInt()).as(Title.class); // Title id not null assertThat(postTitleRs.getId(), Matchers.notNullValue()); @@ -129,12 +126,12 @@ void testPostTitle() { // Negative cases // Unable to create title test int status400 = HttpStatus.HTTP_BAD_REQUEST.toInt(); - verifyPostResponse(TITLES_ENDPOINT, JsonObject.mapFrom(postTitleRq).encode(), prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID_WITH_ACQ_UNITS, ALL_DESIRED_PERMISSIONS_HEADER, + verifyPostResponse(TITLES_ENDPOINT, JsonObject.mapFrom(postTitleRq).encode(), prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID_WITH_ACQ_UNITS, ALL_DESIRED_ACQ_PERMISSIONS_HEADER, new Header(X_ECHO_STATUS, String.valueOf(status400))), APPLICATION_JSON, status400); // Internal error on mod-orders-storage test int status500 = HttpStatus.HTTP_INTERNAL_SERVER_ERROR.toInt(); - verifyPostResponse(TITLES_ENDPOINT, JsonObject.mapFrom(postTitleRq).encode(), prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID_WITH_ACQ_UNITS, ALL_DESIRED_PERMISSIONS_HEADER, + verifyPostResponse(TITLES_ENDPOINT, JsonObject.mapFrom(postTitleRq).encode(), prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID_WITH_ACQ_UNITS, ALL_DESIRED_ACQ_PERMISSIONS_HEADER, new Header(X_ECHO_STATUS, String.valueOf(status500))), APPLICATION_JSON, status500); } @@ -163,7 +160,7 @@ void postTitleWithInvalidClaimingConfig() throws Exception { String reqData = getMockData(TITLES_MOCK_DATA_PATH + "title_invalid_claiming_config.json"); - List errors = verifyPostResponse(TITLES_ENDPOINT, reqData, prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID, ALL_DESIRED_PERMISSIONS_HEADER), APPLICATION_JSON, 422) + List errors = verifyPostResponse(TITLES_ENDPOINT, reqData, prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID, ALL_DESIRED_ACQ_PERMISSIONS_HEADER), APPLICATION_JSON, 422) .as(Errors.class) .getErrors(); @@ -192,7 +189,7 @@ void titleShouldBePopulatedFromPackagePoLine() { addMockEntry(PO_LINES_STORAGE, JsonObject.mapFrom(packagePoLine)); Title titleWithPackagePoLineRS = verifyPostResponse(TITLES_ENDPOINT, JsonObject.mapFrom(titleWithPackagePoLineRQ).encode(), - prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID, ALL_DESIRED_PERMISSIONS_HEADER), APPLICATION_JSON, HttpStatus.HTTP_CREATED.toInt()).as(Title.class); + prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, X_OKAPI_USER_ID, ALL_DESIRED_ACQ_PERMISSIONS_HEADER), APPLICATION_JSON, HttpStatus.HTTP_CREATED.toInt()).as(Title.class); assertEquals(titleWithPackagePoLineRS.getPackageName(), packageTitleName); assertNotNull(titleWithPackagePoLineRS.getExpectedReceiptDate()); @@ -231,7 +228,7 @@ void testPutTitlesByIdTest() { .withAcqUnitIds(List.of(ACQ_UNIT_ID)); verifyPut(String.format(TITLES_ID_PATH, SAMPLE_TITLE_ID), JsonObject.mapFrom(reqData).encode(), - prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, ALL_DESIRED_PERMISSIONS_HEADER), "", 204); + prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, ALL_DESIRED_ACQ_PERMISSIONS_HEADER), "", 204); } @Test diff --git a/src/test/java/org/folio/service/routinglist/RoutingListServiceTest.java b/src/test/java/org/folio/service/RoutingListsServiceTest.java similarity index 86% rename from src/test/java/org/folio/service/routinglist/RoutingListServiceTest.java rename to src/test/java/org/folio/service/RoutingListsServiceTest.java index 23b620f77..f1bdf6e68 100644 --- a/src/test/java/org/folio/service/routinglist/RoutingListServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListsServiceTest.java @@ -1,6 +1,7 @@ -package org.folio.service.routinglist; +package org.folio.service; import static io.vertx.core.Future.succeededFuture; +import static org.folio.TestConstants.ROUTING_LIST_ID; import static org.folio.TestUtils.getMockData; import static org.folio.rest.impl.MockServer.ROUTING_LIST_MOCK_DATA_PATH; import static org.folio.rest.impl.MockServer.USERS_MOCK_DATA_PATH; @@ -19,7 +20,6 @@ import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; import org.folio.rest.jaxrs.model.RoutingList; -import org.folio.service.UserService; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -29,11 +29,10 @@ import org.mockito.MockitoAnnotations; @ExtendWith(VertxExtension.class) -public class RoutingListServiceTest { +public class RoutingListsServiceTest { - private static final String ROUTING_LIST_ID = "eee951de-ea49-400a-96e8-705ae5a1e1e8"; @InjectMocks - RoutingListService routingListService; + RoutingListsService routingListsService; @Mock private RestClient restClient; @Mock @@ -55,7 +54,7 @@ void processTemplate(VertxTestContext vertxTestContext) throws IOException { doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any(RequestContext.class)); doReturn(succeededFuture(new JsonObject())).when(restClient).post(anyString(), any(), eq(JsonObject.class), any()); - Future future = routingListService.processTemplateEngine(ROUTING_LIST_ID, requestContextMock); + Future future = routingListsService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); vertxTestContext.assertComplete(future) .onComplete(result -> { From 7dc0657bfe9635b26ac4352c169e4d5b10d68387 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Fri, 29 Mar 2024 13:57:18 +0500 Subject: [PATCH 08/35] [MODORSERS-1026] - Fixed logs issue --- src/main/java/org/folio/service/RoutingListsService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListsService.java index b6b064ebf..9f4358c14 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -9,16 +9,17 @@ import io.vertx.core.Future; import io.vertx.core.json.JsonObject; -import lombok.extern.log4j.Log4j2; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.folio.models.TemplateProcessingRequest; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; import org.folio.rest.jaxrs.model.RoutingList; -@Log4j2 public class RoutingListsService { + private static final Logger log = LogManager.getLogger(); private static final String ENDPOINT = resourcesPath(ROUTING_LISTS); private static final String BY_ID_ENDPOINT = ENDPOINT + "/{id}"; private final RestClient restClient; From d83c8ab72271c667fb77df4891a7d78104b29275 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Fri, 29 Mar 2024 14:14:37 +0500 Subject: [PATCH 09/35] [MODORSERS-1026] - added hashcode in TemplateProcessingRequest --- .../folio/models/TemplateProcessingRequest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/org/folio/models/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java index ef01972dd..73df78e4e 100644 --- a/src/main/java/org/folio/models/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -1,6 +1,7 @@ package org.folio.models; import java.util.List; +import java.util.Objects; import java.util.UUID; import lombok.Getter; @@ -62,5 +63,20 @@ public Item setName(String name) { return this; } } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof TemplateProcessingRequest that)) return false; + return Objects.equals(templateId, that.templateId) + && Objects.equals(lang, that.lang) + && Objects.equals(outputFormat, that.outputFormat) + && Objects.equals(context, that.context); + } + + @Override + public int hashCode() { + return Objects.hash(templateId, lang, outputFormat, context); + } } From 48e3ee4b5a33ca2e47f35a6c5aef7f8ec0625b28 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Fri, 29 Mar 2024 14:34:36 +0500 Subject: [PATCH 10/35] [MODORSERS-1026] - Added jsonProperty annotation --- .../models/TemplateProcessingRequest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/org/folio/models/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java index 73df78e4e..7c1c77c44 100644 --- a/src/main/java/org/folio/models/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -4,15 +4,41 @@ import java.util.Objects; import java.util.UUID; +import com.fasterxml.jackson.annotation.JsonProperty; + import lombok.Getter; @Getter public class TemplateProcessingRequest { + @JsonProperty private UUID templateId; + @JsonProperty private String lang; + @JsonProperty private String outputFormat; + @JsonProperty private Context context; + public TemplateProcessingRequest setTemplateId(UUID templateId) { + this.templateId = templateId; + return this; + } + + public TemplateProcessingRequest setLang(String lang) { + this.lang = lang; + return this; + } + + public TemplateProcessingRequest setOutputFormat(String outputFormat) { + this.outputFormat = outputFormat; + return this; + } + + public TemplateProcessingRequest setContext(Context context) { + this.context = context; + return this; + } + public TemplateProcessingRequest withTemplateId(UUID templateId) { this.templateId = templateId; return this; From e94d73d0a71f455d436ef2ba2d683cc61021e86e Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Fri, 29 Mar 2024 14:52:44 +0500 Subject: [PATCH 11/35] [MODORSERS-1026] - Added jsonProperty annotation --- src/main/java/org/folio/models/TemplateProcessingRequest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/folio/models/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java index 7c1c77c44..638eeaae5 100644 --- a/src/main/java/org/folio/models/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -61,7 +61,9 @@ public TemplateProcessingRequest withContext(Context context) { @Getter public static class Context { + @JsonProperty private List users; + @JsonProperty private List items; public Context withUsers(List users) { @@ -73,6 +75,7 @@ public Context withUsers(List users) { @Getter public static class User { + @JsonProperty private String name; public User withName(String name) { this.name = name; @@ -82,6 +85,7 @@ public User withName(String name) { @Getter public static class Item { + @JsonProperty private String name; public Item setName(String name) { From 155ea13d5046f4b2fe02917f4a0fd8c3fe7d8cc8 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Fri, 29 Mar 2024 15:03:03 +0500 Subject: [PATCH 12/35] [MODORSERS-1026] - tmp log level changed --- src/main/resources/log4j2.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/log4j2.properties b/src/main/resources/log4j2.properties index 04837a067..1a974c3b8 100644 --- a/src/main/resources/log4j2.properties +++ b/src/main/resources/log4j2.properties @@ -5,7 +5,7 @@ packages = org.folio.okapi.common.logging filters = threshold filter.threshold.type = ThresholdFilter -filter.threshold.level = info +filter.threshold.level = debug appenders = console @@ -14,6 +14,6 @@ appender.console.name = STDOUT appender.console.layout.type = PatternLayout appender.console.layout.pattern = %d{HH:mm:ss:SS} [$${FolioLoggingContext:requestid}] [$${FolioLoggingContext:tenantid}] [$${FolioLoggingContext:userid}] [$${FolioLoggingContext:moduleid}] %-5p %-20.40C{1} %m%n -rootLogger.level = info -rootLogger.appenderRefs = info +rootLogger.level = debug +rootLogger.appenderRefs = debug rootLogger.appenderRef.stdout.ref = STDOUT From e12d91c9a9a1e69f18aced15e2a0ad26c187e2f4 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Fri, 29 Mar 2024 16:36:36 +0500 Subject: [PATCH 13/35] [MODORSERS-1026] - Fixed jsonObject converting error --- src/main/java/org/folio/service/UserService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/folio/service/UserService.java b/src/main/java/org/folio/service/UserService.java index 8b088d55b..1e074db94 100644 --- a/src/main/java/org/folio/service/UserService.java +++ b/src/main/java/org/folio/service/UserService.java @@ -32,6 +32,6 @@ public Future getUsersByIds(List userIds, RequestContext req .withLimit(Integer.MAX_VALUE) .withQuery(convertIdsToCqlQuery(userIds, "id")); - return restClient.get(requestEntry, JsonObject.class, requestContext); + return restClient.getAsJsonObject(requestEntry, requestContext); } } From 15d5f35dff3009258468cd3d30c74dcc0c1d20ce Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Fri, 29 Mar 2024 16:49:09 +0500 Subject: [PATCH 14/35] [MODORSERS-1026] - Fixed endpoint --- .../java/org/folio/service/RoutingListsService.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListsService.java index 9f4358c14..1b0bc282a 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -20,8 +20,10 @@ public class RoutingListsService { private static final Logger log = LogManager.getLogger(); - private static final String ENDPOINT = resourcesPath(ROUTING_LISTS); - private static final String BY_ID_ENDPOINT = ENDPOINT + "/{id}"; + private static final String ROUTING_LIST_ENDPOINT = resourcesPath(ROUTING_LISTS); + private static final String ROUTING_LIST_BY_ID_ENDPOINT = ROUTING_LIST_ENDPOINT + "/{id}"; + private static final String TEMPLATE_REQUEST_ENDPOINT = resourcesPath(TEMPLATE_REQUEST); + private final RestClient restClient; private final UserService userService; @@ -38,7 +40,7 @@ public Future processTemplateRequest(String routingListId, RequestCo } public Future getRoutingListById(String routingListId, RequestContext requestContext) { - var requestEntry = new RequestEntry(BY_ID_ENDPOINT).withId(routingListId); + var requestEntry = new RequestEntry(ROUTING_LIST_BY_ID_ENDPOINT).withId(routingListId); return restClient.get(requestEntry, RoutingList.class, requestContext); } @@ -73,6 +75,6 @@ private List createUserListForContext(JsonObject } private Future postTemplateRequest(TemplateProcessingRequest templateProcessingRequest, RequestContext requestContext) { - return restClient.post(TEMPLATE_REQUEST, JsonObject.mapFrom(templateProcessingRequest), JsonObject.class, requestContext); + return restClient.post(TEMPLATE_REQUEST_ENDPOINT, JsonObject.mapFrom(templateProcessingRequest), JsonObject.class, requestContext); } } From 274616e3fa89705951e4dc31854b3a3c68106029 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Mon, 1 Apr 2024 18:05:02 +0500 Subject: [PATCH 15/35] [MODORSERS-1026] - Added tests --- .../org/folio/rest/impl/RoutingListsAPI.java | 3 + .../folio/service/RoutingListsService.java | 6 +- src/test/java/org/folio/ApiTestSuite.java | 5 + .../folio/rest/impl/RoutingListsApiTest.java | 113 ++++++++++++++++++ .../eee951de-ea49-400a-96e8-705ae5a1e1e8.json | 2 +- .../mockdata/users/user_collection.json | 80 +++++++------ 6 files changed, 169 insertions(+), 40 deletions(-) create mode 100644 src/test/java/org/folio/rest/impl/RoutingListsApiTest.java diff --git a/src/main/java/org/folio/rest/impl/RoutingListsAPI.java b/src/main/java/org/folio/rest/impl/RoutingListsAPI.java index 430bb79d3..1844e767d 100644 --- a/src/main/java/org/folio/rest/impl/RoutingListsAPI.java +++ b/src/main/java/org/folio/rest/impl/RoutingListsAPI.java @@ -1,5 +1,7 @@ package org.folio.rest.impl; +import static io.vertx.core.Future.succeededFuture; + import javax.ws.rs.core.Response; import java.util.Map; @@ -40,6 +42,7 @@ public void postOrdersRoutingLists(RoutingList entity, Map okapi public void postOrdersRoutingListsProcessTemplateById(String id, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { routingListsService.processTemplateRequest(id, new RequestContext(vertxContext, okapiHeaders)) + .onSuccess(jsonObject -> asyncResultHandler.handle(succeededFuture(this.buildOkResponse(jsonObject)))) .onFailure(t -> handleErrorResponse(asyncResultHandler, t)); } } diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListsService.java index 1b0bc282a..b97d32cdd 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -20,6 +20,7 @@ public class RoutingListsService { private static final Logger log = LogManager.getLogger(); + private static final UUID TEMPLATE_REQUEST_ID = UUID.fromString("9465105a-e8a1-470c-9817-142d33bc4fcd"); private static final String ROUTING_LIST_ENDPOINT = resourcesPath(ROUTING_LISTS); private static final String ROUTING_LIST_BY_ID_ENDPOINT = ROUTING_LIST_ENDPOINT + "/{id}"; private static final String TEMPLATE_REQUEST_ENDPOINT = resourcesPath(TEMPLATE_REQUEST); @@ -60,7 +61,7 @@ private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, private TemplateProcessingRequest createBaseTemplateRequest() { return new TemplateProcessingRequest() - .withTemplateId(UUID.randomUUID()) + .withTemplateId(TEMPLATE_REQUEST_ID) .withLang("en") .withOutputFormat("text/plain"); } @@ -75,6 +76,7 @@ private List createUserListForContext(JsonObject } private Future postTemplateRequest(TemplateProcessingRequest templateProcessingRequest, RequestContext requestContext) { - return restClient.post(TEMPLATE_REQUEST_ENDPOINT, JsonObject.mapFrom(templateProcessingRequest), JsonObject.class, requestContext); + var requestEntry = new RequestEntry(TEMPLATE_REQUEST_ENDPOINT); + return restClient.postJsonObject(requestEntry, JsonObject.mapFrom(templateProcessingRequest), requestContext); } } diff --git a/src/test/java/org/folio/ApiTestSuite.java b/src/test/java/org/folio/ApiTestSuite.java index 9d83c7424..5faea3544 100644 --- a/src/test/java/org/folio/ApiTestSuite.java +++ b/src/test/java/org/folio/ApiTestSuite.java @@ -33,6 +33,7 @@ import org.folio.rest.impl.PurchaseOrderLinesApiTest; import org.folio.rest.impl.PurchaseOrdersApiTest; import org.folio.rest.impl.ReceivingHistoryApiTest; +import org.folio.rest.impl.RoutingListsApiTest; import org.folio.rest.impl.TitlesApiTest; import org.folio.rest.impl.crud.ConfigurationCrudTest; import org.folio.rest.impl.protection.LinesProtectionTest; @@ -182,6 +183,10 @@ class OrderTemplateTestNested extends OrderTemplateTest { class TitlesApiTestNested extends TitlesApiTest { } + @Nested + class RoutingListsApiTestNested extends RoutingListsApiTest { + } + @Nested class ConfigurationCrudTestNested extends ConfigurationCrudTest { } diff --git a/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java b/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java new file mode 100644 index 000000000..be1bb567d --- /dev/null +++ b/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java @@ -0,0 +1,113 @@ +package org.folio.rest.impl; + +import static io.vertx.core.Future.succeededFuture; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.folio.RestTestUtils.prepareHeaders; +import static org.folio.RestTestUtils.verifyPostResponse; +import static org.folio.TestConfig.X_OKAPI_URL; +import static org.folio.TestConfig.autowireDependencies; +import static org.folio.TestConfig.clearServiceInteractions; +import static org.folio.TestConfig.getFirstContextFromVertx; +import static org.folio.TestConfig.getVertx; +import static org.folio.TestConfig.initSpringContext; +import static org.folio.TestConfig.isVerticleNotDeployed; +import static org.folio.TestConfig.mockPort; +import static org.folio.TestConstants.EMPTY_CONFIG_X_OKAPI_TENANT; +import static org.folio.TestConstants.ROUTING_LIST_ID; +import static org.folio.TestConstants.X_OKAPI_TOKEN; +import static org.folio.TestConstants.X_OKAPI_USER_ID; +import static org.folio.rest.RestConstants.OKAPI_URL; +import static org.folio.rest.impl.PurchaseOrdersApiTest.X_OKAPI_TENANT; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import io.vertx.core.Context; +import io.vertx.core.json.JsonObject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.folio.ApiTestSuite; +import org.folio.rest.core.models.RequestContext; +import org.folio.service.RoutingListsService; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; + +public class RoutingListsApiTest { + + private static final Logger logger = LogManager.getLogger(); + private static final String TEMPLATE_PROCESSING_REQUEST_ENDPOINT = "orders/routing-lists/" + ROUTING_LIST_ID + "/process-template"; + private static boolean runningOnOwn; + @Autowired + private RoutingListsService routingListsService; + private RequestContext requestContext; + private Context ctxMock; + private Map okapiHeadersMock; + + @BeforeAll + static void before() throws InterruptedException, ExecutionException, TimeoutException { + if (isVerticleNotDeployed()) { + ApiTestSuite.before(); + runningOnOwn = true; + } + initSpringContext(RoutingListsApiTest.ContextConfiguration.class); + } + + + @BeforeEach + void beforeEach() { + MockitoAnnotations.openMocks(this); + autowireDependencies(this); + ctxMock = getFirstContextFromVertx(getVertx()); + okapiHeadersMock = new HashMap<>(); + okapiHeadersMock.put(OKAPI_URL, "http://localhost:" + mockPort); + okapiHeadersMock.put(X_OKAPI_TOKEN.getName(), X_OKAPI_TOKEN.getValue()); + okapiHeadersMock.put(X_OKAPI_TENANT.getName(), X_OKAPI_TENANT.getValue()); + okapiHeadersMock.put(X_OKAPI_USER_ID.getName(), X_OKAPI_USER_ID.getValue()); + requestContext = new RequestContext(ctxMock, okapiHeadersMock); + } + + @AfterEach + void afterEach() { + clearServiceInteractions(); + } + + @AfterAll + static void after() { + if (runningOnOwn) { + ApiTestSuite.after(); + } + } + + @Test + void testProcessTemplateRequest() { + logger.info("=== Test Execute template processing request ==="); + + doReturn(succeededFuture(new JsonObject())).when(routingListsService).processTemplateRequest(eq(ROUTING_LIST_ID), any(RequestContext.class)); + + verifyPostResponse(TEMPLATE_PROCESSING_REQUEST_ENDPOINT, "", + prepareHeaders(X_OKAPI_URL, EMPTY_CONFIG_X_OKAPI_TENANT), APPLICATION_JSON, 200); + + verify(routingListsService, times(1)).processTemplateRequest(eq(ROUTING_LIST_ID), any(RequestContext.class)); + } + + static class ContextConfiguration { + @Bean + public RoutingListsService routingListsService() { + return mock(RoutingListsService.class); + } + } +} diff --git a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json index d89742eb8..e172458bb 100644 --- a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json +++ b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json @@ -1,5 +1,5 @@ { - "id": "c0d13648-347b-4ac9-8c2f-5bc47248b87e", + "id": "eee951de-ea49-400a-96e8-705ae5a1e1e8", "_version": 1, "name": "Mars expedition", "notes": "Future note", diff --git a/src/test/resources/mockdata/users/user_collection.json b/src/test/resources/mockdata/users/user_collection.json index 2473888ff..e6d1ebb3e 100644 --- a/src/test/resources/mockdata/users/user_collection.json +++ b/src/test/resources/mockdata/users/user_collection.json @@ -1,41 +1,47 @@ { - "users": [ - { - "username": "mockuser8", - "id": "d926d900-e27d-46d6-bba8-31e9d5c2cf44", - "active": true, - "type": "staff", - "meta": { - "creation_date": "2016-11-05T0723", - "last_login_date": "" - }, - "personal": { - "firstName": "Albert", - "lastName": "Einstein", - "email": "albert@si.edu", - "phone": "927-306-2327" - } + "users" : [ { + "username" : "sallie", + "id" : "00bc2807-4d5b-4a27-a2b5-b7b1ba431cc4", + "barcode" : "133143370961512", + "active" : false, + "type" : "patron", + "patronGroup" : "503a81cd-6c26-400f-b620-14c08943697c", + "departments" : [ ], + "proxyFor" : [ ], + "personal" : { + "lastName" : "Denesik", + "firstName" : "Maiya", + "middleName" : "Noel", + "email" : "ahmad@kertzmann-bailey-and-brekke.io", + "phone" : "759.693.8557", + "mobilePhone" : "(557)093-7575", + "dateOfBirth" : "2009-07-21T00:00:00.000+00:00", + "addresses" : [ { + "countryId" : "US", + "addressLine1" : "17691 Rodriguez Divide", + "city" : "Birmingham", + "region" : "CO", + "postalCode" : "85748", + "addressTypeId" : "93d3d88d-499b-45d0-9bc7-ac73c3a19880", + "primaryAddress" : true + } ], + "preferredContactTypeId" : "002" }, - { - "username": "mockuser9", - "id": "077274ad-6b4f-4c28-9779-6d381e7a1ca1", - "active": true, - "type": "staff", - "meta": { - "creation_date": "2016-11-05T0723", - "last_login_date": "" - }, - "personal": { - "lastName": "Mockerson", - "middleName": "M.", - "firstName": "Mickey", - "email": "mock@biglibrary.org", - "phone": "2125551212", - "mobilePhone": "112233" - }, - "externalSystemId": "123", - "barcode": "test123" + "enrollmentDate" : "2015-04-13T00:00:00.000+00:00", + "expirationDate" : "2019-06-20T00:00:00.000+00:00", + "createdDate" : "2024-01-28T16:01:21.650+00:00", + "updatedDate" : "2024-01-28T16:01:21.650+00:00", + "metadata" : { + "createdDate" : "2024-01-28T16:01:21.601+00:00", + "createdByUserId" : "631fdcc3-c7c6-48e6-b51c-8a727c5d3dd7", + "updatedDate" : "2024-01-28T16:01:21.601+00:00", + "updatedByUserId" : "631fdcc3-c7c6-48e6-b51c-8a727c5d3dd7" } - ], - "totalRecords": 2 + } ], + "totalRecords" : 1, + "resultInfo" : { + "totalRecords" : 1, + "facets" : [ ], + "diagnostics" : [ ] + } } From 413be739964ff38f26a535c44a61c17706604a01 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Mon, 1 Apr 2024 18:17:21 +0500 Subject: [PATCH 16/35] [MODORSERS-1026] - Fixed tests --- src/test/java/org/folio/service/RoutingListsServiceTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/org/folio/service/RoutingListsServiceTest.java b/src/test/java/org/folio/service/RoutingListsServiceTest.java index f1bdf6e68..3e6f4a05e 100644 --- a/src/test/java/org/folio/service/RoutingListsServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListsServiceTest.java @@ -6,7 +6,6 @@ import static org.folio.rest.impl.MockServer.ROUTING_LIST_MOCK_DATA_PATH; import static org.folio.rest.impl.MockServer.USERS_MOCK_DATA_PATH; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; @@ -52,7 +51,7 @@ void processTemplate(VertxTestContext vertxTestContext) throws IOException { doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any(RequestContext.class)); doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any(RequestContext.class)); - doReturn(succeededFuture(new JsonObject())).when(restClient).post(anyString(), any(), eq(JsonObject.class), any()); + doReturn(succeededFuture(new JsonObject())).when(restClient).postJsonObject(any(RequestEntry.class), any(), any()); Future future = routingListsService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); From 672461340a90af55ac861665350453dd2a13d0e1 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Tue, 2 Apr 2024 15:05:30 +0500 Subject: [PATCH 17/35] [MODORSERS-1026] - Improved template request context --- .../models/TemplateProcessingRequest.java | 73 ++++++++++--------- .../folio/service/RoutingListsService.java | 45 ++++++++---- 2 files changed, 70 insertions(+), 48 deletions(-) diff --git a/src/main/java/org/folio/models/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java index 638eeaae5..1a1e553e7 100644 --- a/src/main/java/org/folio/models/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -39,69 +39,74 @@ public TemplateProcessingRequest setContext(Context context) { return this; } - public TemplateProcessingRequest withTemplateId(UUID templateId) { - this.templateId = templateId; - return this; - } - - public TemplateProcessingRequest withLang(String lang) { - this.lang = lang; - return this; - } - - public TemplateProcessingRequest withOutputFormat(String outputFormat) { - this.outputFormat = outputFormat; - return this; - } - - public TemplateProcessingRequest withContext(Context context) { - this.context = context; - return this; - } - @Getter public static class Context { @JsonProperty - private List users; + private RoutingList routingList; @JsonProperty - private List items; + private List users; - public Context withUsers(List users) { - this.users = users; + public Context setRoutingList(RoutingList routingList) { + this.routingList = routingList; return this; } + public Context setUsers(List users) { + this.users = users; + return this; + } } @Getter - public static class User { + public static class RoutingList { @JsonProperty private String name; - public User withName(String name) { + @JsonProperty + private String note; + + public RoutingList setName(String name) { this.name = name; return this; } + + public RoutingList setNote(String note) { + this.note = note; + return this; + } } @Getter - public static class Item { + public static class User { @JsonProperty - private String name; + private String lastName; + @JsonProperty + private String firstName; + @JsonProperty + private String routingAddress; - public Item setName(String name) { - this.name = name; + public User setLastName(String lastName) { + this.lastName = lastName; + return this; + } + + public User setFirstName(String firstName) { + this.firstName = firstName; return this; } - } + public User setRoutingAddress(String routingAddress) { + this.routingAddress = routingAddress; + return this; + } + } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof TemplateProcessingRequest that)) return false; return Objects.equals(templateId, that.templateId) - && Objects.equals(lang, that.lang) - && Objects.equals(outputFormat, that.outputFormat) - && Objects.equals(context, that.context); + && Objects.equals(lang, that.lang) + && Objects.equals(outputFormat, that.outputFormat) + && Objects.equals(context, that.context); } @Override diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListsService.java index b97d32cdd..acbd93cbf 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -52,31 +52,48 @@ private Future fetchUsersAndCreateTemplate(RoutingLis private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, JsonObject users) { var templateRequest = createBaseTemplateRequest(); - var userListForContext = createUserListForContext(users); - var context = new TemplateProcessingRequest.Context().withUsers(userListForContext); - templateRequest.withContext(context); - log.info("createTemplateRequest:: TemplateProcessingRequest object created : {}", JsonObject.mapFrom(templateRequest).encodePrettily()); + var usersForContext = createUsersForContext(users); + var routingListForContext = createRoutingListForContext(routingList); + templateRequest.setContext(new TemplateProcessingRequest.Context() + .setRoutingList(routingListForContext) + .setUsers(usersForContext)); + log.info("createTemplateRequest:: TemplateProcessingRequest object created for routing list name: {}", + templateRequest.getContext().getRoutingList().getName()); + // troubleshoot purposes, it will be removed because it contains personal information + log.info("createTemplateRequest:: TemplateProcessingRequest object created : {}", + JsonObject.mapFrom(templateRequest).encodePrettily()); return templateRequest; } private TemplateProcessingRequest createBaseTemplateRequest() { return new TemplateProcessingRequest() - .withTemplateId(TEMPLATE_REQUEST_ID) - .withLang("en") - .withOutputFormat("text/plain"); + .setTemplateId(TEMPLATE_REQUEST_ID) + .setLang("en") + .setOutputFormat("text/plain"); } - private List createUserListForContext(JsonObject users) { + private List createUsersForContext(JsonObject users) { return users.getJsonArray("users").stream() .map(JsonObject.class::cast) - .map(user -> new TemplateProcessingRequest.User() - .withName(user.getJsonObject("personal").getString("firstName")) - ) - .toList(); + .map(user -> user.getJsonObject("personal")) + .map(personalData -> + new TemplateProcessingRequest.User() + .setFirstName(personalData.getString("firstName")) + .setLastName(personalData.getString("lastName")) + .setRoutingAddress(personalData.getJsonArray("addresses") + .getJsonObject(0).getString("addressLine1")) + ).toList(); } - private Future postTemplateRequest(TemplateProcessingRequest templateProcessingRequest, RequestContext requestContext) { + private TemplateProcessingRequest.RoutingList createRoutingListForContext(RoutingList routingList) { + return new TemplateProcessingRequest.RoutingList() + .setName(routingList.getName()) + .setNote(routingList.getNotes()); + } + + private Future postTemplateRequest(TemplateProcessingRequest templateRequest, RequestContext requestContext) { var requestEntry = new RequestEntry(TEMPLATE_REQUEST_ENDPOINT); - return restClient.postJsonObject(requestEntry, JsonObject.mapFrom(templateProcessingRequest), requestContext); + log.info("postTemplateRequest:: Sending template request with routing list name={}", templateRequest.getContext().getRoutingList().getName()); + return restClient.postJsonObject(requestEntry, JsonObject.mapFrom(templateRequest), requestContext); } } From b2a135f23c902cec4f50b969e60b171f4b1f39b6 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Tue, 2 Apr 2024 15:14:53 +0500 Subject: [PATCH 18/35] [MODORSERS-1026] - Improved template request context --- .../models/TemplateProcessingRequest.java | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/folio/models/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java index 1a1e553e7..854ab8b9d 100644 --- a/src/main/java/org/folio/models/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -6,9 +6,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; - -@Getter public class TemplateProcessingRequest { @JsonProperty private UUID templateId; @@ -19,6 +16,22 @@ public class TemplateProcessingRequest { @JsonProperty private Context context; + public UUID getTemplateId() { + return templateId; + } + + public String getLang() { + return lang; + } + + public String getOutputFormat() { + return outputFormat; + } + + public Context getContext() { + return context; + } + public TemplateProcessingRequest setTemplateId(UUID templateId) { this.templateId = templateId; return this; @@ -39,13 +52,20 @@ public TemplateProcessingRequest setContext(Context context) { return this; } - @Getter public static class Context { @JsonProperty private RoutingList routingList; @JsonProperty private List users; + public RoutingList getRoutingList() { + return routingList; + } + + public List getUsers() { + return users; + } + public Context setRoutingList(RoutingList routingList) { this.routingList = routingList; return this; @@ -57,13 +77,20 @@ public Context setUsers(List users) { } } - @Getter public static class RoutingList { @JsonProperty private String name; @JsonProperty private String note; + public String getName() { + return name; + } + + public String getNote() { + return note; + } + public RoutingList setName(String name) { this.name = name; return this; @@ -75,7 +102,6 @@ public RoutingList setNote(String note) { } } - @Getter public static class User { @JsonProperty private String lastName; @@ -84,6 +110,18 @@ public static class User { @JsonProperty private String routingAddress; + public String getLastName() { + return lastName; + } + + public String getFirstName() { + return firstName; + } + + public String getRoutingAddress() { + return routingAddress; + } + public User setLastName(String lastName) { this.lastName = lastName; return this; @@ -99,6 +137,7 @@ public User setRoutingAddress(String routingAddress) { return this; } } + @Override public boolean equals(Object o) { if (this == o) return true; From 980c3377d90fb2006bbb6fd1ba2fcbcf721046c8 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Tue, 2 Apr 2024 16:39:39 +0500 Subject: [PATCH 19/35] [MODORSERS-1026] - Improved template request context --- ramls/acq-models | 2 +- .../org/folio/models/TemplateProcessingRequest.java | 10 +++++----- src/main/java/org/folio/rest/core/RestClient.java | 6 ++++-- .../java/org/folio/service/RoutingListsService.java | 8 +++++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/ramls/acq-models b/ramls/acq-models index a3385f315..264917d88 160000 --- a/ramls/acq-models +++ b/ramls/acq-models @@ -1 +1 @@ -Subproject commit a3385f315835414e45422041ecb249ba7f2fc028 +Subproject commit 264917d88c6847a54c588102ab5b58ea933f02cc diff --git a/src/main/java/org/folio/models/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java index 854ab8b9d..2dc391e63 100644 --- a/src/main/java/org/folio/models/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -81,14 +81,14 @@ public static class RoutingList { @JsonProperty private String name; @JsonProperty - private String note; + private String notes; public String getName() { return name; } - public String getNote() { - return note; + public String getNotes() { + return notes; } public RoutingList setName(String name) { @@ -96,8 +96,8 @@ public RoutingList setName(String name) { return this; } - public RoutingList setNote(String note) { - this.note = note; + public RoutingList setNotes(String notes) { + this.notes = notes; return this; } } diff --git a/src/main/java/org/folio/rest/core/RestClient.java b/src/main/java/org/folio/rest/core/RestClient.java index 14d846ca5..d95ac0f29 100644 --- a/src/main/java/org/folio/rest/core/RestClient.java +++ b/src/main/java/org/folio/rest/core/RestClient.java @@ -242,12 +242,14 @@ public Future getAsJsonObject(RequestEntry requestEntry, RequestCont public String extractRecordId(HttpResponse response) { JsonObject body = response.bodyAsJsonObject(); - String id; + String id = ""; if (body != null && !body.isEmpty() && body.containsKey(ID)) { id = body.getString(ID); } else { String location = response.getHeader(LOCATION); - id = location.substring(location.lastIndexOf('/') + 1); + if (location != null) { + id = location.substring(location.lastIndexOf('/') + 1); + } } return id; } diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListsService.java index acbd93cbf..da7ce2b9e 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -21,6 +21,8 @@ public class RoutingListsService { private static final Logger log = LogManager.getLogger(); private static final UUID TEMPLATE_REQUEST_ID = UUID.fromString("9465105a-e8a1-470c-9817-142d33bc4fcd"); + private static final String TEMPLATE_REQUEST_LANG = "en"; + private static final String TEMPLATE_REQUEST_OUTPUT = "text/html"; private static final String ROUTING_LIST_ENDPOINT = resourcesPath(ROUTING_LISTS); private static final String ROUTING_LIST_BY_ID_ENDPOINT = ROUTING_LIST_ENDPOINT + "/{id}"; private static final String TEMPLATE_REQUEST_ENDPOINT = resourcesPath(TEMPLATE_REQUEST); @@ -68,8 +70,8 @@ private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, private TemplateProcessingRequest createBaseTemplateRequest() { return new TemplateProcessingRequest() .setTemplateId(TEMPLATE_REQUEST_ID) - .setLang("en") - .setOutputFormat("text/plain"); + .setLang(TEMPLATE_REQUEST_LANG) + .setOutputFormat(TEMPLATE_REQUEST_OUTPUT); } private List createUsersForContext(JsonObject users) { @@ -88,7 +90,7 @@ private List createUsersForContext(JsonObject us private TemplateProcessingRequest.RoutingList createRoutingListForContext(RoutingList routingList) { return new TemplateProcessingRequest.RoutingList() .setName(routingList.getName()) - .setNote(routingList.getNotes()); + .setNotes(routingList.getNotes()); } private Future postTemplateRequest(TemplateProcessingRequest templateRequest, RequestContext requestContext) { From 7e4980bef277ea9dc0a8144c4ed3c20c8d8b8538 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Tue, 2 Apr 2024 17:41:31 +0500 Subject: [PATCH 20/35] [MODORSERS-1026] - Changed api design --- ramls/routing-lists.raml | 7 +++++-- src/main/java/org/folio/rest/impl/RoutingListsAPI.java | 4 ++-- src/test/java/org/folio/rest/impl/RoutingListsApiTest.java | 6 +++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ramls/routing-lists.raml b/ramls/routing-lists.raml index 3593957bf..b98725dad 100644 --- a/ramls/routing-lists.raml +++ b/ramls/routing-lists.raml @@ -35,10 +35,13 @@ resourceTypes: searchable: {description: "with valid searchable fields: for example routing list", example: "[\"routing_list\", \"ROUTING_LIST\", \"=\"]"}, pageable ] - /{id}/process-template: + post: + description: Create routing lists + + /{id}/template: uriParameters: id: description: The UUID of a Title type: UUID - post: + get: description: Execute mod-template-engine to process templates with replaced token placeholders [update] diff --git a/src/main/java/org/folio/rest/impl/RoutingListsAPI.java b/src/main/java/org/folio/rest/impl/RoutingListsAPI.java index 1844e767d..60dbdbd38 100644 --- a/src/main/java/org/folio/rest/impl/RoutingListsAPI.java +++ b/src/main/java/org/folio/rest/impl/RoutingListsAPI.java @@ -39,8 +39,8 @@ public void postOrdersRoutingLists(RoutingList entity, Map okapi } @Override - public void postOrdersRoutingListsProcessTemplateById(String id, Map okapiHeaders, - Handler> asyncResultHandler, Context vertxContext) { + public void getOrdersRoutingListsTemplateById(String id, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { routingListsService.processTemplateRequest(id, new RequestContext(vertxContext, okapiHeaders)) .onSuccess(jsonObject -> asyncResultHandler.handle(succeededFuture(this.buildOkResponse(jsonObject)))) .onFailure(t -> handleErrorResponse(asyncResultHandler, t)); diff --git a/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java b/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java index be1bb567d..e9344a1c3 100644 --- a/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java +++ b/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java @@ -3,7 +3,7 @@ import static io.vertx.core.Future.succeededFuture; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static org.folio.RestTestUtils.prepareHeaders; -import static org.folio.RestTestUtils.verifyPostResponse; +import static org.folio.RestTestUtils.verifyGet; import static org.folio.TestConfig.X_OKAPI_URL; import static org.folio.TestConfig.autowireDependencies; import static org.folio.TestConfig.clearServiceInteractions; @@ -98,8 +98,8 @@ void testProcessTemplateRequest() { doReturn(succeededFuture(new JsonObject())).when(routingListsService).processTemplateRequest(eq(ROUTING_LIST_ID), any(RequestContext.class)); - verifyPostResponse(TEMPLATE_PROCESSING_REQUEST_ENDPOINT, "", - prepareHeaders(X_OKAPI_URL, EMPTY_CONFIG_X_OKAPI_TENANT), APPLICATION_JSON, 200); + verifyGet(TEMPLATE_PROCESSING_REQUEST_ENDPOINT, prepareHeaders(X_OKAPI_URL, EMPTY_CONFIG_X_OKAPI_TENANT), + APPLICATION_JSON, 200); verify(routingListsService, times(1)).processTemplateRequest(eq(ROUTING_LIST_ID), any(RequestContext.class)); } From fa557e52afc2f5ebd03cc567902e7c9435bb2dc6 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Tue, 2 Apr 2024 17:54:45 +0500 Subject: [PATCH 21/35] [MODORSERS-1026] - Fixed test --- .../java/org/folio/rest/impl/RoutingListsApiTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java b/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java index e9344a1c3..5c889f305 100644 --- a/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java +++ b/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java @@ -49,13 +49,15 @@ public class RoutingListsApiTest { private static final Logger logger = LogManager.getLogger(); - private static final String TEMPLATE_PROCESSING_REQUEST_ENDPOINT = "orders/routing-lists/" + ROUTING_LIST_ID + "/process-template"; + private static final String TEMPLATE_PROCESSING_REQUEST_ENDPOINT = "orders/routing-lists/" + ROUTING_LIST_ID + "/template"; private static boolean runningOnOwn; @Autowired private RoutingListsService routingListsService; private RequestContext requestContext; private Context ctxMock; private Map okapiHeadersMock; + private AutoCloseable mockitoMocks; + @BeforeAll static void before() throws InterruptedException, ExecutionException, TimeoutException { @@ -69,7 +71,7 @@ static void before() throws InterruptedException, ExecutionException, TimeoutExc @BeforeEach void beforeEach() { - MockitoAnnotations.openMocks(this); + mockitoMocks = MockitoAnnotations.openMocks(this); autowireDependencies(this); ctxMock = getFirstContextFromVertx(getVertx()); okapiHeadersMock = new HashMap<>(); @@ -81,7 +83,8 @@ void beforeEach() { } @AfterEach - void afterEach() { + void afterEach() throws Exception { + mockitoMocks.close(); clearServiceInteractions(); } From 929aabac6dab151cfe66df168a70a46fcbfd7a5c Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Tue, 2 Apr 2024 18:16:08 +0500 Subject: [PATCH 22/35] [MODORSERS-1026] - Updated descriptor --- descriptors/ModuleDescriptor-template.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index a1be1fb65..7d7e05e73 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -1004,9 +1004,9 @@ "handlers": [ { "methods": ["POST"], - "pathPattern": "/orders/routing-lists/{id}/process-template", + "pathPattern": "/orders/routing-lists/{id}/template", "permissionsRequired": [ - "orders.routing-list.item.post" + "orders.routing-list-template.item.get" ] } ] @@ -1719,9 +1719,9 @@ "description" : "Holding summary" }, { - "permissionName": "orders.routing-list.item.post", - "displayName" : "orders routing-list item post", - "description" : "Orders routing-list item post" + "permissionName": "orders.routing-list-template.item.get", + "displayName" : "orders routing-list-template item get", + "description" : "Orders routing-list-template item get" }, { "permissionName": "orders.all", @@ -1758,7 +1758,7 @@ "orders.holding-summary.collection.get", "orders.acquisition-methods.all", "orders.export-history.all", - "orders.routing-list.item.post" + "orders.routing-list-template.item.get" ] }, { From 7ff500a273bfbf64385f7ca2100dee1f10b17814 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Tue, 2 Apr 2024 18:28:37 +0500 Subject: [PATCH 23/35] [MODORSERS-1026] - Updated descriptor --- descriptors/ModuleDescriptor-template.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 7d7e05e73..0b951d96a 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -1003,7 +1003,7 @@ "version": "1.0", "handlers": [ { - "methods": ["POST"], + "methods": ["GET"], "pathPattern": "/orders/routing-lists/{id}/template", "permissionsRequired": [ "orders.routing-list-template.item.get" From 31888b9cbe7e815092ace396973bd657fc7af866 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Wed, 3 Apr 2024 14:06:10 +0500 Subject: [PATCH 24/35] [MODORSERS-1026] - Created dto object for userCollection --- .../models/TemplateProcessingRequest.java | 22 +++---- .../java/org/folio/models/UserCollection.java | 60 +++++++++++++++++++ .../folio/service/RoutingListsService.java | 51 +++++++++------- .../java/org/folio/service/UserService.java | 11 ++-- src/main/resources/log4j2.properties | 6 +- .../service/RoutingListsServiceTest.java | 16 +++-- 6 files changed, 122 insertions(+), 44 deletions(-) create mode 100644 src/main/java/org/folio/models/UserCollection.java diff --git a/src/main/java/org/folio/models/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java index 2dc391e63..97ec96cf3 100644 --- a/src/main/java/org/folio/models/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -32,22 +32,22 @@ public Context getContext() { return context; } - public TemplateProcessingRequest setTemplateId(UUID templateId) { + public TemplateProcessingRequest withTemplateId(UUID templateId) { this.templateId = templateId; return this; } - public TemplateProcessingRequest setLang(String lang) { + public TemplateProcessingRequest withLang(String lang) { this.lang = lang; return this; } - public TemplateProcessingRequest setOutputFormat(String outputFormat) { + public TemplateProcessingRequest withOutputFormat(String outputFormat) { this.outputFormat = outputFormat; return this; } - public TemplateProcessingRequest setContext(Context context) { + public TemplateProcessingRequest withContext(Context context) { this.context = context; return this; } @@ -66,12 +66,12 @@ public List getUsers() { return users; } - public Context setRoutingList(RoutingList routingList) { + public Context withRoutingList(RoutingList routingList) { this.routingList = routingList; return this; } - public Context setUsers(List users) { + public Context withUsers(List users) { this.users = users; return this; } @@ -91,12 +91,12 @@ public String getNotes() { return notes; } - public RoutingList setName(String name) { + public RoutingList withName(String name) { this.name = name; return this; } - public RoutingList setNotes(String notes) { + public RoutingList withNotes(String notes) { this.notes = notes; return this; } @@ -122,17 +122,17 @@ public String getRoutingAddress() { return routingAddress; } - public User setLastName(String lastName) { + public User withLastName(String lastName) { this.lastName = lastName; return this; } - public User setFirstName(String firstName) { + public User withFirstName(String firstName) { this.firstName = firstName; return this; } - public User setRoutingAddress(String routingAddress) { + public User withRoutingAddress(String routingAddress) { this.routingAddress = routingAddress; return this; } diff --git a/src/main/java/org/folio/models/UserCollection.java b/src/main/java/org/folio/models/UserCollection.java new file mode 100644 index 000000000..1d1a6a4b1 --- /dev/null +++ b/src/main/java/org/folio/models/UserCollection.java @@ -0,0 +1,60 @@ +package org.folio.models; + +import java.util.List; +import java.util.UUID; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.folio.rest.acq.model.Address; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class UserCollection { + @JsonProperty + private List users; + @JsonProperty + private int totalRecords; + + public List getUsers() { + return users; + } + public int getTotalRecords() { + return totalRecords; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class User { + @JsonProperty + private UUID id; + @JsonProperty + private Personal personal; + + public UUID getId () { + return id; + } + public Personal getPersonal () { + return personal; + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Personal { + @JsonProperty + private String firstName; + @JsonProperty + private String lastName; + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) + private List
addresses; + + public String getFirstName() { + return firstName; + } + public String getLastName() { + return lastName; + } + public List
getAddresses() { + return addresses; + } + } + } +} diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListsService.java index da7ce2b9e..84801d5ea 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -4,7 +4,9 @@ import static org.folio.orders.utils.ResourcePathResolver.TEMPLATE_REQUEST; import static org.folio.orders.utils.ResourcePathResolver.resourcesPath; +import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.UUID; import io.vertx.core.Future; @@ -12,6 +14,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.folio.models.TemplateProcessingRequest; +import org.folio.models.UserCollection; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; @@ -52,13 +55,13 @@ private Future fetchUsersAndCreateTemplate(RoutingLis .map(users -> createTemplateRequest(routingList, users)); } - private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, JsonObject users) { + private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, UserCollection users) { var templateRequest = createBaseTemplateRequest(); var usersForContext = createUsersForContext(users); var routingListForContext = createRoutingListForContext(routingList); - templateRequest.setContext(new TemplateProcessingRequest.Context() - .setRoutingList(routingListForContext) - .setUsers(usersForContext)); + templateRequest.withContext(new TemplateProcessingRequest.Context() + .withRoutingList(routingListForContext) + .withUsers(usersForContext)); log.info("createTemplateRequest:: TemplateProcessingRequest object created for routing list name: {}", templateRequest.getContext().getRoutingList().getName()); // troubleshoot purposes, it will be removed because it contains personal information @@ -69,33 +72,41 @@ private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, private TemplateProcessingRequest createBaseTemplateRequest() { return new TemplateProcessingRequest() - .setTemplateId(TEMPLATE_REQUEST_ID) - .setLang(TEMPLATE_REQUEST_LANG) - .setOutputFormat(TEMPLATE_REQUEST_OUTPUT); + .withTemplateId(TEMPLATE_REQUEST_ID) + .withLang(TEMPLATE_REQUEST_LANG) + .withOutputFormat(TEMPLATE_REQUEST_OUTPUT); } - private List createUsersForContext(JsonObject users) { - return users.getJsonArray("users").stream() - .map(JsonObject.class::cast) - .map(user -> user.getJsonObject("personal")) - .map(personalData -> - new TemplateProcessingRequest.User() - .setFirstName(personalData.getString("firstName")) - .setLastName(personalData.getString("lastName")) - .setRoutingAddress(personalData.getJsonArray("addresses") - .getJsonObject(0).getString("addressLine1")) + private List createUsersForContext(UserCollection userCollection) { + if (userCollection.getUsers().isEmpty()) { + return Collections.emptyList(); + } + + return userCollection.getUsers().stream() + .map(UserCollection.User::getPersonal) + .filter(Objects::nonNull) + .map(personalData -> { + var userForContext = new TemplateProcessingRequest.User() + .withFirstName(personalData.getFirstName()) + .withLastName(personalData.getLastName()); + var addresses = personalData.getAddresses(); + if (addresses != null && !addresses.isEmpty()){ + userForContext.withRoutingAddress(addresses.get(0).getAddressLine1()); + } + return userForContext; + } ).toList(); } private TemplateProcessingRequest.RoutingList createRoutingListForContext(RoutingList routingList) { return new TemplateProcessingRequest.RoutingList() - .setName(routingList.getName()) - .setNotes(routingList.getNotes()); + .withName(routingList.getName()) + .withNotes(routingList.getNotes()); } private Future postTemplateRequest(TemplateProcessingRequest templateRequest, RequestContext requestContext) { var requestEntry = new RequestEntry(TEMPLATE_REQUEST_ENDPOINT); log.info("postTemplateRequest:: Sending template request with routing list name={}", templateRequest.getContext().getRoutingList().getName()); - return restClient.postJsonObject(requestEntry, JsonObject.mapFrom(templateRequest), requestContext); + return restClient.post(requestEntry, JsonObject.mapFrom(templateRequest), JsonObject.class, requestContext); } } diff --git a/src/main/java/org/folio/service/UserService.java b/src/main/java/org/folio/service/UserService.java index 1e074db94..338ef663c 100644 --- a/src/main/java/org/folio/service/UserService.java +++ b/src/main/java/org/folio/service/UserService.java @@ -9,12 +9,13 @@ import java.util.Map; import io.vertx.core.Future; -import io.vertx.core.json.JsonObject; +import org.folio.models.UserCollection; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; public class UserService { + private static final String USERS_ENDPOINT = resourcesPath(USERS); private final RestClient restClient; @@ -26,12 +27,10 @@ public static String getCurrentUserId(Map okapiHeaders) { return okapiHeaders.get(OKAPI_USERID_HEADER); } - public Future getUsersByIds(List userIds, RequestContext requestContext) { - var requestEntry = new RequestEntry(USERS_ENDPOINT) - .withOffset(0) - .withLimit(Integer.MAX_VALUE) + public Future getUsersByIds(List userIds, RequestContext requestContext) { + var requestEntry = new RequestEntry(USERS_ENDPOINT).withOffset(0).withLimit(Integer.MAX_VALUE) .withQuery(convertIdsToCqlQuery(userIds, "id")); - return restClient.getAsJsonObject(requestEntry, requestContext); + return restClient.get(requestEntry, UserCollection.class, requestContext); } } diff --git a/src/main/resources/log4j2.properties b/src/main/resources/log4j2.properties index 1a974c3b8..04837a067 100644 --- a/src/main/resources/log4j2.properties +++ b/src/main/resources/log4j2.properties @@ -5,7 +5,7 @@ packages = org.folio.okapi.common.logging filters = threshold filter.threshold.type = ThresholdFilter -filter.threshold.level = debug +filter.threshold.level = info appenders = console @@ -14,6 +14,6 @@ appender.console.name = STDOUT appender.console.layout.type = PatternLayout appender.console.layout.pattern = %d{HH:mm:ss:SS} [$${FolioLoggingContext:requestid}] [$${FolioLoggingContext:tenantid}] [$${FolioLoggingContext:userid}] [$${FolioLoggingContext:moduleid}] %-5p %-20.40C{1} %m%n -rootLogger.level = debug -rootLogger.appenderRefs = debug +rootLogger.level = info +rootLogger.appenderRefs = info rootLogger.appenderRef.stdout.ref = STDOUT diff --git a/src/test/java/org/folio/service/RoutingListsServiceTest.java b/src/test/java/org/folio/service/RoutingListsServiceTest.java index 3e6f4a05e..656f05c94 100644 --- a/src/test/java/org/folio/service/RoutingListsServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListsServiceTest.java @@ -15,10 +15,12 @@ import io.vertx.core.json.JsonObject; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; +import org.folio.models.UserCollection; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; import org.folio.rest.jaxrs.model.RoutingList; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -38,20 +40,26 @@ public class RoutingListsServiceTest { private UserService userService; @Mock private RequestContext requestContextMock; + private AutoCloseable mockitoMocks; @BeforeEach - public void initMocks() { - MockitoAnnotations.openMocks(this); + public void initMocks() throws Exception { + mockitoMocks = MockitoAnnotations.openMocks(this); + } + + @AfterEach + void afterEach() throws Exception { + mockitoMocks.close(); } @Test void processTemplate(VertxTestContext vertxTestContext) throws IOException { var routingList = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + ".json")).mapTo(RoutingList.class); - var users = new JsonObject(getMockData(USERS_MOCK_DATA_PATH + "user_collection.json")); + var users = new JsonObject(getMockData(USERS_MOCK_DATA_PATH + "user_collection.json")).mapTo(UserCollection.class); doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any(RequestContext.class)); doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any(RequestContext.class)); - doReturn(succeededFuture(new JsonObject())).when(restClient).postJsonObject(any(RequestEntry.class), any(), any()); + doReturn(succeededFuture(new JsonObject())).when(restClient).post(any(RequestEntry.class), any(), any(), any()); Future future = routingListsService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); From 6a23713719ebf2495f6338ac13832c38176890bc Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Wed, 3 Apr 2024 14:33:20 +0500 Subject: [PATCH 25/35] [MODORSERS-1026] - Improved tests and fixed jsonObject issue --- .../org/folio/service/RoutingListsService.java | 2 +- .../folio/service/RoutingListsServiceTest.java | 4 ++-- ...8-705ae5a1e1e8-expected-template-request.json | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListsService.java index 84801d5ea..d077f5ea3 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -107,6 +107,6 @@ private TemplateProcessingRequest.RoutingList createRoutingListForContext(Routin private Future postTemplateRequest(TemplateProcessingRequest templateRequest, RequestContext requestContext) { var requestEntry = new RequestEntry(TEMPLATE_REQUEST_ENDPOINT); log.info("postTemplateRequest:: Sending template request with routing list name={}", templateRequest.getContext().getRoutingList().getName()); - return restClient.post(requestEntry, JsonObject.mapFrom(templateRequest), JsonObject.class, requestContext); + return restClient.postJsonObject(requestEntry, JsonObject.mapFrom(templateRequest), requestContext); } } diff --git a/src/test/java/org/folio/service/RoutingListsServiceTest.java b/src/test/java/org/folio/service/RoutingListsServiceTest.java index 656f05c94..f108cb03b 100644 --- a/src/test/java/org/folio/service/RoutingListsServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListsServiceTest.java @@ -56,10 +56,10 @@ void afterEach() throws Exception { void processTemplate(VertxTestContext vertxTestContext) throws IOException { var routingList = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + ".json")).mapTo(RoutingList.class); var users = new JsonObject(getMockData(USERS_MOCK_DATA_PATH + "user_collection.json")).mapTo(UserCollection.class); - + var expectedTemplateRequest = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + "-expected-template-request.json")); doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any(RequestContext.class)); doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any(RequestContext.class)); - doReturn(succeededFuture(new JsonObject())).when(restClient).post(any(RequestEntry.class), any(), any(), any()); + doReturn(succeededFuture(new JsonObject())).when(restClient).postJsonObject(any(RequestEntry.class), eq(expectedTemplateRequest), any()); Future future = routingListsService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); diff --git a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json new file mode 100644 index 000000000..7f726b4a6 --- /dev/null +++ b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json @@ -0,0 +1,16 @@ +{ + "templateId" : "9465105a-e8a1-470c-9817-142d33bc4fcd", + "lang" : "en", + "outputFormat" : "text/html", + "context" : { + "routingList" : { + "name" : "Mars expedition", + "notes" : "Future note" + }, + "users" : [ { + "lastName" : "Denesik", + "firstName" : "Maiya", + "routingAddress" : "17691 Rodriguez Divide" + } ] + } +} From a301ec02df20216f92e329b9b86eadeddd8776f3 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Wed, 3 Apr 2024 15:55:50 +0500 Subject: [PATCH 26/35] [MODORSERS-1026] - Prepared to code-review --- src/main/java/org/folio/service/RoutingListsService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListsService.java index d077f5ea3..2aeae0744 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListsService.java @@ -64,9 +64,6 @@ private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, .withUsers(usersForContext)); log.info("createTemplateRequest:: TemplateProcessingRequest object created for routing list name: {}", templateRequest.getContext().getRoutingList().getName()); - // troubleshoot purposes, it will be removed because it contains personal information - log.info("createTemplateRequest:: TemplateProcessingRequest object created : {}", - JsonObject.mapFrom(templateRequest).encodePrettily()); return templateRequest; } From 6945eb69e5d98fe939fe819537200228ca42e942 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Wed, 3 Apr 2024 16:04:18 +0500 Subject: [PATCH 27/35] [MODORSERS-1026] - Minor improvement --- src/main/java/org/folio/orders/utils/ResourcePathResolver.java | 2 -- src/main/java/org/folio/service/UserService.java | 1 - 2 files changed, 3 deletions(-) diff --git a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java index fbc72ccdf..b6e426bd3 100644 --- a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java +++ b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java @@ -30,7 +30,6 @@ private ResourcePathResolver() { public static final String TITLES = "titles"; public static final String ROUTING_LISTS = "routingLists"; public static final String TEMPLATE_REQUEST = "templateRequest"; - public static final String PROCESS_TEMPLATE = "processTemplate"; public static final String USERS = "users"; public static final String FUNDS = "finance.funds"; public static final String BUDGETS = "finance.budgets"; @@ -72,7 +71,6 @@ private ResourcePathResolver() { apis.put(ORDER_TEMPLATES, "/orders-storage/order-templates"); apis.put(ROUTING_LISTS, "/orders-storage/routing-lists"); apis.put(TEMPLATE_REQUEST, "/template-request"); - apis.put(PROCESS_TEMPLATE, "/process-template"); apis.put(FUNDS, "/finance/funds"); apis.put(BUDGETS, "/finance/budgets"); apis.put(LEDGERS, "/finance-storage/ledgers"); diff --git a/src/main/java/org/folio/service/UserService.java b/src/main/java/org/folio/service/UserService.java index 338ef663c..25256e2fe 100644 --- a/src/main/java/org/folio/service/UserService.java +++ b/src/main/java/org/folio/service/UserService.java @@ -30,7 +30,6 @@ public static String getCurrentUserId(Map okapiHeaders) { public Future getUsersByIds(List userIds, RequestContext requestContext) { var requestEntry = new RequestEntry(USERS_ENDPOINT).withOffset(0).withLimit(Integer.MAX_VALUE) .withQuery(convertIdsToCqlQuery(userIds, "id")); - return restClient.get(requestEntry, UserCollection.class, requestContext); } } From 689877a4169126015148026659b07bfaa994c86a Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Wed, 3 Apr 2024 19:42:20 +0500 Subject: [PATCH 28/35] [MODORSERS-1026] - Major improvement --- descriptors/ModuleDescriptor-template.json | 13 +++- .../org/folio/config/ApplicationConfig.java | 6 +- .../models/TemplateProcessingRequest.java | 29 ++------- .../java/org/folio/models/UserCollection.java | 5 ++ .../orders/utils/ResourcePathResolver.java | 8 ++- .../org/folio/rest/impl/RoutingListsAPI.java | 6 +- ...tsService.java => RoutingListService.java} | 59 +++++++++++++------ .../java/org/folio/service/UserService.java | 20 +++++++ src/test/java/org/folio/ApiTestSuite.java | 4 +- .../folio/rest/impl/RoutingListsApiTest.java | 12 ++-- ...eTest.java => RoutingListServiceTest.java} | 17 ++++-- ...05ae5a1e1e8-expected-template-request.json | 3 +- 12 files changed, 113 insertions(+), 69 deletions(-) rename src/main/java/org/folio/service/{RoutingListsService.java => RoutingListService.java} (62%) rename src/test/java/org/folio/service/{RoutingListsServiceTest.java => RoutingListServiceTest.java} (80%) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 0b951d96a..16657bee1 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -1005,9 +1005,8 @@ { "methods": ["GET"], "pathPattern": "/orders/routing-lists/{id}/template", - "permissionsRequired": [ - "orders.routing-list-template.item.get" - ] + "permissionsRequired": ["orders.routing-list-template.item.get"], + "modulePermissions": ["template-request.post"] } ] }, @@ -1211,6 +1210,14 @@ { "id": "user-tenants", "version": "1.0" + }, + { + "id": "users", + "version": "16.0" + }, + { + "id": "template-engine", + "version": "2.2" } ], "optional": [ diff --git a/src/main/java/org/folio/config/ApplicationConfig.java b/src/main/java/org/folio/config/ApplicationConfig.java index 52c05c36b..6c1a45321 100644 --- a/src/main/java/org/folio/config/ApplicationConfig.java +++ b/src/main/java/org/folio/config/ApplicationConfig.java @@ -112,7 +112,7 @@ import org.folio.service.pieces.flows.update.PieceUpdateFlowInventoryManager; import org.folio.service.pieces.flows.update.PieceUpdateFlowManager; import org.folio.service.pieces.flows.update.PieceUpdateFlowPoLineService; -import org.folio.service.RoutingListsService; +import org.folio.service.RoutingListService; import org.folio.service.titles.TitleValidationService; import org.folio.service.titles.TitlesService; import org.springframework.beans.factory.annotation.Qualifier; @@ -437,8 +437,8 @@ CompositeOrderDynamicDataPopulateService combinedPopulateService(CompositeOrderR } @Bean - RoutingListsService routingListService(RestClient restClient, UserService userService) { - return new RoutingListsService(restClient, userService); + RoutingListService routingListService(RestClient restClient, UserService userService) { + return new RoutingListService(restClient, userService); } @Bean diff --git a/src/main/java/org/folio/models/TemplateProcessingRequest.java b/src/main/java/org/folio/models/TemplateProcessingRequest.java index 97ec96cf3..7646ecfc6 100644 --- a/src/main/java/org/folio/models/TemplateProcessingRequest.java +++ b/src/main/java/org/folio/models/TemplateProcessingRequest.java @@ -4,8 +4,11 @@ import java.util.Objects; import java.util.UUID; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import org.folio.rest.jaxrs.model.RoutingList; + public class TemplateProcessingRequest { @JsonProperty private UUID templateId; @@ -54,6 +57,7 @@ public TemplateProcessingRequest withContext(Context context) { public static class Context { @JsonProperty + @JsonInclude(JsonInclude.Include.NON_EMPTY) private RoutingList routingList; @JsonProperty private List users; @@ -77,31 +81,6 @@ public Context withUsers(List users) { } } - public static class RoutingList { - @JsonProperty - private String name; - @JsonProperty - private String notes; - - public String getName() { - return name; - } - - public String getNotes() { - return notes; - } - - public RoutingList withName(String name) { - this.name = name; - return this; - } - - public RoutingList withNotes(String notes) { - this.notes = notes; - return this; - } - } - public static class User { @JsonProperty private String lastName; diff --git a/src/main/java/org/folio/models/UserCollection.java b/src/main/java/org/folio/models/UserCollection.java index 1d1a6a4b1..860ca7d01 100644 --- a/src/main/java/org/folio/models/UserCollection.java +++ b/src/main/java/org/folio/models/UserCollection.java @@ -22,6 +22,11 @@ public int getTotalRecords() { return totalRecords; } + public UserCollection withUsers(List users) { + this.users = users; + return this; + } + @JsonIgnoreProperties(ignoreUnknown = true) public static class User { @JsonProperty diff --git a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java index b6e426bd3..01613131d 100644 --- a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java +++ b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java @@ -28,9 +28,7 @@ private ResourcePathResolver() { public static final String PAYMENT_STATUS = "paymentStatus"; public static final String ORDER_TEMPLATES = "orderTemplates"; public static final String TITLES = "titles"; - public static final String ROUTING_LISTS = "routingLists"; public static final String TEMPLATE_REQUEST = "templateRequest"; - public static final String USERS = "users"; public static final String FUNDS = "finance.funds"; public static final String BUDGETS = "finance.budgets"; public static final String LEDGERS = "finance.ledgers"; @@ -50,6 +48,9 @@ private ResourcePathResolver() { public static final String ORDER_INVOICE_RELATIONSHIP = "order-invoice-relationship"; public static final String EXPORT_HISTORY = "export-history"; public static final String TAGS = "tags"; + public static final String ROUTING_LISTS = "routingLists"; + public static final String ORDER_SETTINGS = "orderSettings"; + public static final String USERS = "users"; private static final Map SUB_OBJECT_ITEM_APIS; private static final Map SUB_OBJECT_COLLECTION_APIS; @@ -69,7 +70,6 @@ private ResourcePathResolver() { apis.put(RECEIVING_HISTORY, "/orders-storage/receiving-history"); apis.put(PO_LINE_NUMBER, "/orders-storage/po-line-number"); apis.put(ORDER_TEMPLATES, "/orders-storage/order-templates"); - apis.put(ROUTING_LISTS, "/orders-storage/routing-lists"); apis.put(TEMPLATE_REQUEST, "/template-request"); apis.put(FUNDS, "/finance/funds"); apis.put(BUDGETS, "/finance/budgets"); @@ -92,6 +92,8 @@ private ResourcePathResolver() { apis.put(EXPORT_HISTORY, "/orders-storage/export-history"); apis.put(TAGS, "/tags"); apis.put(USERS, "/users"); + apis.put(ORDER_SETTINGS, "/order-storage/settings"); + apis.put(ROUTING_LISTS, "/orders-storage/routing-lists"); SUB_OBJECT_COLLECTION_APIS = Collections.unmodifiableMap(apis); SUB_OBJECT_ITEM_APIS = Collections.unmodifiableMap( diff --git a/src/main/java/org/folio/rest/impl/RoutingListsAPI.java b/src/main/java/org/folio/rest/impl/RoutingListsAPI.java index 60dbdbd38..23a61328d 100644 --- a/src/main/java/org/folio/rest/impl/RoutingListsAPI.java +++ b/src/main/java/org/folio/rest/impl/RoutingListsAPI.java @@ -13,14 +13,14 @@ import org.folio.rest.core.models.RequestContext; import org.folio.rest.jaxrs.model.RoutingList; import org.folio.rest.jaxrs.resource.OrdersRoutingLists; -import org.folio.service.RoutingListsService; +import org.folio.service.RoutingListService; import org.folio.spring.SpringContextUtil; import org.springframework.beans.factory.annotation.Autowired; public class RoutingListsAPI extends BaseApi implements OrdersRoutingLists { @Autowired - private RoutingListsService routingListsService; + private RoutingListService routingListService; public RoutingListsAPI() { SpringContextUtil.autowireDependencies(this, Vertx.currentContext()); @@ -41,7 +41,7 @@ public void postOrdersRoutingLists(RoutingList entity, Map okapi @Override public void getOrdersRoutingListsTemplateById(String id, Map okapiHeaders, Handler> asyncResultHandler, Context vertxContext) { - routingListsService.processTemplateRequest(id, new RequestContext(vertxContext, okapiHeaders)) + routingListService.processTemplateRequest(id, new RequestContext(vertxContext, okapiHeaders)) .onSuccess(jsonObject -> asyncResultHandler.handle(succeededFuture(this.buildOkResponse(jsonObject)))) .onFailure(t -> handleErrorResponse(asyncResultHandler, t)); } diff --git a/src/main/java/org/folio/service/RoutingListsService.java b/src/main/java/org/folio/service/RoutingListService.java similarity index 62% rename from src/main/java/org/folio/service/RoutingListsService.java rename to src/main/java/org/folio/service/RoutingListService.java index 2aeae0744..c7a235974 100644 --- a/src/main/java/org/folio/service/RoutingListsService.java +++ b/src/main/java/org/folio/service/RoutingListService.java @@ -1,5 +1,6 @@ package org.folio.service; +import static org.folio.orders.utils.ResourcePathResolver.ORDER_SETTINGS; import static org.folio.orders.utils.ResourcePathResolver.ROUTING_LISTS; import static org.folio.orders.utils.ResourcePathResolver.TEMPLATE_REQUEST; import static org.folio.orders.utils.ResourcePathResolver.resourcesPath; @@ -11,29 +12,36 @@ import io.vertx.core.Future; import io.vertx.core.json.JsonObject; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.kafka.common.errors.ResourceNotFoundException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.folio.models.TemplateProcessingRequest; import org.folio.models.UserCollection; +import org.folio.rest.acq.model.Address; +import org.folio.rest.acq.model.Setting; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; import org.folio.rest.jaxrs.model.RoutingList; -public class RoutingListsService { +public class RoutingListService { private static final Logger log = LogManager.getLogger(); private static final UUID TEMPLATE_REQUEST_ID = UUID.fromString("9465105a-e8a1-470c-9817-142d33bc4fcd"); private static final String TEMPLATE_REQUEST_LANG = "en"; private static final String TEMPLATE_REQUEST_OUTPUT = "text/html"; private static final String ROUTING_LIST_ENDPOINT = resourcesPath(ROUTING_LISTS); + private static final String ORDER_SETTINGS_ENDPOINT = resourcesPath(ORDER_SETTINGS); + private static final String ROUTING_USER_ADDRESS_TYPE_ID = "ROUTING_USER_ADDRESS_TYPE_ID"; private static final String ROUTING_LIST_BY_ID_ENDPOINT = ROUTING_LIST_ENDPOINT + "/{id}"; private static final String TEMPLATE_REQUEST_ENDPOINT = resourcesPath(TEMPLATE_REQUEST); private final RestClient restClient; private final UserService userService; - public RoutingListsService(RestClient restClient, UserService userService) { + public RoutingListService(RestClient restClient, UserService userService) { this.restClient = restClient; this.userService = userService; } @@ -41,7 +49,7 @@ public RoutingListsService(RestClient restClient, UserService userService) { public Future processTemplateRequest(String routingListId, RequestContext requestContext) { log.debug("processTemplateRequest: Tying to process template request for routingListId={}", routingListId); return getRoutingListById(routingListId, requestContext) - .compose(routingList -> fetchUsersAndCreateTemplate(routingList, requestContext)) + .compose(routingList -> getUsersAndCreateTemplate(routingList, requestContext)) .compose(templateProcessingRequest -> postTemplateRequest(templateProcessingRequest, requestContext)); } @@ -50,18 +58,18 @@ public Future getRoutingListById(String routingListId, RequestConte return restClient.get(requestEntry, RoutingList.class, requestContext); } - private Future fetchUsersAndCreateTemplate(RoutingList routingList, RequestContext requestContext) { - return userService.getUsersByIds(routingList.getUserIds(), requestContext) - .map(users -> createTemplateRequest(routingList, users)); + private Future getUsersAndCreateTemplate(RoutingList routingList, RequestContext requestContext) { + return getAddressTypeId(requestContext) + .compose(addressTypId -> userService.getUsersByIds(routingList.getUserIds(), requestContext) + .map(users -> createTemplateRequest(routingList, users, addressTypId))); } - private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, UserCollection users) { + private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, UserCollection users, String addressTypeId) { var templateRequest = createBaseTemplateRequest(); - var usersForContext = createUsersForContext(users); - var routingListForContext = createRoutingListForContext(routingList); templateRequest.withContext(new TemplateProcessingRequest.Context() - .withRoutingList(routingListForContext) - .withUsers(usersForContext)); + .withRoutingList(fillRoutingListForContext(routingList)) + .withUsers(fillUsersForContext(users, addressTypeId))); + log.info("createTemplateRequest:: TemplateProcessingRequest object created for routing list name: {}", templateRequest.getContext().getRoutingList().getName()); return templateRequest; @@ -74,11 +82,10 @@ private TemplateProcessingRequest createBaseTemplateRequest() { .withOutputFormat(TEMPLATE_REQUEST_OUTPUT); } - private List createUsersForContext(UserCollection userCollection) { + private List fillUsersForContext(UserCollection userCollection, String addressTypeId) { if (userCollection.getUsers().isEmpty()) { return Collections.emptyList(); } - return userCollection.getUsers().stream() .map(UserCollection.User::getPersonal) .filter(Objects::nonNull) @@ -86,17 +93,33 @@ private List createUsersForContext(UserCollectio var userForContext = new TemplateProcessingRequest.User() .withFirstName(personalData.getFirstName()) .withLastName(personalData.getLastName()); - var addresses = personalData.getAddresses(); - if (addresses != null && !addresses.isEmpty()){ - userForContext.withRoutingAddress(addresses.get(0).getAddressLine1()); + var addressList = personalData.getAddresses(); + if (addressList != null && !addressList.isEmpty()) { + userForContext.withRoutingAddress(getUserAddress(addressList, addressTypeId)); } return userForContext; } ).toList(); } - private TemplateProcessingRequest.RoutingList createRoutingListForContext(RoutingList routingList) { - return new TemplateProcessingRequest.RoutingList() + private String getUserAddress(List
addressList, String addressTypeId) { + return addressList.get(0).getAddressLine1(); + } + + private Future getAddressTypeId(RequestContext requestContext) { + var requestEntry = new RequestEntry(ORDER_SETTINGS_ENDPOINT) + .withQuery("key=" + ROUTING_USER_ADDRESS_TYPE_ID); + return restClient.get(requestEntry, Setting.class, requestContext) + .map(setting -> { + if (ObjectUtils.isEmpty(setting) || StringUtils.isBlank(setting.getValue())) { + throw new ResourceNotFoundException("Setting is not found for addressTypeId"); + } + return setting.getValue(); + }); + } + + private RoutingList fillRoutingListForContext(RoutingList routingList) { + return new RoutingList() .withName(routingList.getName()) .withNotes(routingList.getNotes()); } diff --git a/src/main/java/org/folio/service/UserService.java b/src/main/java/org/folio/service/UserService.java index 25256e2fe..97aa93b75 100644 --- a/src/main/java/org/folio/service/UserService.java +++ b/src/main/java/org/folio/service/UserService.java @@ -1,14 +1,18 @@ package org.folio.service; +import static org.folio.orders.utils.HelperUtils.collectResultsOnSuccess; import static org.folio.orders.utils.HelperUtils.convertIdsToCqlQuery; import static org.folio.orders.utils.ResourcePathResolver.USERS; import static org.folio.orders.utils.ResourcePathResolver.resourcesPath; +import static org.folio.rest.RestConstants.MAX_IDS_FOR_GET_RQ_15; import static org.folio.rest.RestVerticle.OKAPI_USERID_HEADER; import java.util.List; import java.util.Map; import io.vertx.core.Future; +import one.util.streamex.StreamEx; +import org.apache.commons.lang3.ObjectUtils; import org.folio.models.UserCollection; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; @@ -28,8 +32,24 @@ public static String getCurrentUserId(Map okapiHeaders) { } public Future getUsersByIds(List userIds, RequestContext requestContext) { + var futures = StreamEx.ofSubLists(userIds, MAX_IDS_FOR_GET_RQ_15) + .map(ids -> getBatchUsersByIds(ids, requestContext)) + .toList(); + return collectResultsOnSuccess(futures) + .map(this::combineUserCollections); + } + + private Future getBatchUsersByIds(List userIds, RequestContext requestContext) { var requestEntry = new RequestEntry(USERS_ENDPOINT).withOffset(0).withLimit(Integer.MAX_VALUE) .withQuery(convertIdsToCqlQuery(userIds, "id")); return restClient.get(requestEntry, UserCollection.class, requestContext); } + + private UserCollection combineUserCollections(List userCollections) { + var userList = userCollections.stream() + .filter(ObjectUtils::isNotEmpty) + .flatMap(userCollection -> userCollection.getUsers().stream()) + .toList(); + return new UserCollection().withUsers(userList); + } } diff --git a/src/test/java/org/folio/ApiTestSuite.java b/src/test/java/org/folio/ApiTestSuite.java index 5faea3544..3b2c44d9c 100644 --- a/src/test/java/org/folio/ApiTestSuite.java +++ b/src/test/java/org/folio/ApiTestSuite.java @@ -98,7 +98,7 @@ import org.folio.service.pieces.flows.update.PieceUpdateFlowManagerTest; import org.folio.service.pieces.flows.update.PieceUpdateFlowPoLineServiceTest; import org.folio.service.pieces.validators.PieceValidatorUtilTest; -import org.folio.service.RoutingListsServiceTest; +import org.folio.service.RoutingListServiceTest; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; @@ -478,6 +478,6 @@ class TagServiceTestNested extends TagServiceTest { } @Nested - class RoutingListsServiceTestNested extends RoutingListsServiceTest { + class RoutingListServiceTestNested extends RoutingListServiceTest { } } diff --git a/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java b/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java index 5c889f305..401d0eb9e 100644 --- a/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java +++ b/src/test/java/org/folio/rest/impl/RoutingListsApiTest.java @@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger; import org.folio.ApiTestSuite; import org.folio.rest.core.models.RequestContext; -import org.folio.service.RoutingListsService; +import org.folio.service.RoutingListService; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -52,7 +52,7 @@ public class RoutingListsApiTest { private static final String TEMPLATE_PROCESSING_REQUEST_ENDPOINT = "orders/routing-lists/" + ROUTING_LIST_ID + "/template"; private static boolean runningOnOwn; @Autowired - private RoutingListsService routingListsService; + private RoutingListService routingListService; private RequestContext requestContext; private Context ctxMock; private Map okapiHeadersMock; @@ -99,18 +99,18 @@ static void after() { void testProcessTemplateRequest() { logger.info("=== Test Execute template processing request ==="); - doReturn(succeededFuture(new JsonObject())).when(routingListsService).processTemplateRequest(eq(ROUTING_LIST_ID), any(RequestContext.class)); + doReturn(succeededFuture(new JsonObject())).when(routingListService).processTemplateRequest(eq(ROUTING_LIST_ID), any(RequestContext.class)); verifyGet(TEMPLATE_PROCESSING_REQUEST_ENDPOINT, prepareHeaders(X_OKAPI_URL, EMPTY_CONFIG_X_OKAPI_TENANT), APPLICATION_JSON, 200); - verify(routingListsService, times(1)).processTemplateRequest(eq(ROUTING_LIST_ID), any(RequestContext.class)); + verify(routingListService, times(1)).processTemplateRequest(eq(ROUTING_LIST_ID), any(RequestContext.class)); } static class ContextConfiguration { @Bean - public RoutingListsService routingListsService() { - return mock(RoutingListsService.class); + public RoutingListService routingListService() { + return mock(RoutingListService.class); } } } diff --git a/src/test/java/org/folio/service/RoutingListsServiceTest.java b/src/test/java/org/folio/service/RoutingListServiceTest.java similarity index 80% rename from src/test/java/org/folio/service/RoutingListsServiceTest.java rename to src/test/java/org/folio/service/RoutingListServiceTest.java index f108cb03b..ae9e444c4 100644 --- a/src/test/java/org/folio/service/RoutingListsServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListServiceTest.java @@ -10,12 +10,14 @@ import static org.mockito.Mockito.doReturn; import java.io.IOException; +import java.util.UUID; import io.vertx.core.Future; import io.vertx.core.json.JsonObject; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; import org.folio.models.UserCollection; +import org.folio.rest.acq.model.Setting; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; @@ -30,10 +32,10 @@ import org.mockito.MockitoAnnotations; @ExtendWith(VertxExtension.class) -public class RoutingListsServiceTest { +public class RoutingListServiceTest { @InjectMocks - RoutingListsService routingListsService; + RoutingListService routingListService; @Mock private RestClient restClient; @Mock @@ -57,11 +59,16 @@ void processTemplate(VertxTestContext vertxTestContext) throws IOException { var routingList = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + ".json")).mapTo(RoutingList.class); var users = new JsonObject(getMockData(USERS_MOCK_DATA_PATH + "user_collection.json")).mapTo(UserCollection.class); var expectedTemplateRequest = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + "-expected-template-request.json")); - doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any(RequestContext.class)); - doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any(RequestContext.class)); + var setting = new Setting().withId(UUID.randomUUID().toString()) + .withKey("routing-list") + .withValue("93d3d88d-499b-45d0-9bc7-ac73c3a19880"); + + doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any()); + doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any()); + doReturn(succeededFuture(setting)).when(restClient).get(any(RequestEntry.class), eq(Setting.class), any()); doReturn(succeededFuture(new JsonObject())).when(restClient).postJsonObject(any(RequestEntry.class), eq(expectedTemplateRequest), any()); - Future future = routingListsService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); + Future future = routingListService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); vertxTestContext.assertComplete(future) .onComplete(result -> { diff --git a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json index 7f726b4a6..f5beed65a 100644 --- a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json +++ b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json @@ -5,7 +5,8 @@ "context" : { "routingList" : { "name" : "Mars expedition", - "notes" : "Future note" + "notes" : "Future note", + "userIds": [] }, "users" : [ { "lastName" : "Denesik", From c1c0cdc98c9296be18862e1ae8b38d7458594f8e Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 4 Apr 2024 12:09:16 +0500 Subject: [PATCH 29/35] [MODORSERS-1026] - Fixed logic to get addressLine --- descriptors/ModuleDescriptor-template.json | 6 +- .../java/org/folio/models/UserCollection.java | 17 +- .../org/folio/service/RoutingListService.java | 14 +- .../folio/service/RoutingListServiceTest.java | 6 +- .../org/folio/service/UserServiceTest.java | 65 ++++++++ ...05ae5a1e1e8-expected-template-request.json | 31 ++-- .../eee951de-ea49-400a-96e8-705ae5a1e1e8.json | 4 +- .../mockdata/users/user_collection.json | 145 +++++++++++++----- 8 files changed, 219 insertions(+), 69 deletions(-) create mode 100644 src/test/java/org/folio/service/UserServiceTest.java diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 16657bee1..46e90f423 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -1006,7 +1006,11 @@ "methods": ["GET"], "pathPattern": "/orders/routing-lists/{id}/template", "permissionsRequired": ["orders.routing-list-template.item.get"], - "modulePermissions": ["template-request.post"] + "modulePermissions": [ + "orders-storage.routing-lists.item.get", + "users.collection.get", + "template-request.post" + ] } ] }, diff --git a/src/main/java/org/folio/models/UserCollection.java b/src/main/java/org/folio/models/UserCollection.java index 860ca7d01..889fbe31b 100644 --- a/src/main/java/org/folio/models/UserCollection.java +++ b/src/main/java/org/folio/models/UserCollection.java @@ -6,8 +6,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import org.folio.rest.acq.model.Address; - @JsonIgnoreProperties(ignoreUnknown = true) public class UserCollection { @JsonProperty @@ -48,7 +46,6 @@ public static class Personal { @JsonProperty private String lastName; @JsonProperty - @JsonIgnoreProperties(ignoreUnknown = true) private List
addresses; public String getFirstName() { @@ -60,6 +57,20 @@ public String getLastName() { public List
getAddresses() { return addresses; } + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Address { + @JsonProperty + private String addressLine1; + @JsonProperty + private String addressTypeId; + + public String getAddressLine1() { + return addressLine1; + } + public String getAddressTypeId() { + return addressTypeId; + } + } } } } diff --git a/src/main/java/org/folio/service/RoutingListService.java b/src/main/java/org/folio/service/RoutingListService.java index c7a235974..3e6b23d53 100644 --- a/src/main/java/org/folio/service/RoutingListService.java +++ b/src/main/java/org/folio/service/RoutingListService.java @@ -7,7 +7,6 @@ import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.UUID; import io.vertx.core.Future; @@ -19,7 +18,6 @@ import org.apache.logging.log4j.Logger; import org.folio.models.TemplateProcessingRequest; import org.folio.models.UserCollection; -import org.folio.rest.acq.model.Address; import org.folio.rest.acq.model.Setting; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; @@ -88,12 +86,12 @@ private List fillUsersForContext(UserCollection } return userCollection.getUsers().stream() .map(UserCollection.User::getPersonal) - .filter(Objects::nonNull) + .filter(ObjectUtils::isNotEmpty) .map(personalData -> { var userForContext = new TemplateProcessingRequest.User() .withFirstName(personalData.getFirstName()) .withLastName(personalData.getLastName()); - var addressList = personalData.getAddresses(); + List addressList = personalData.getAddresses(); if (addressList != null && !addressList.isEmpty()) { userForContext.withRoutingAddress(getUserAddress(addressList, addressTypeId)); } @@ -102,8 +100,12 @@ private List fillUsersForContext(UserCollection ).toList(); } - private String getUserAddress(List
addressList, String addressTypeId) { - return addressList.get(0).getAddressLine1(); + private String getUserAddress(List addressList, String addressTypeId) { + for (UserCollection.User.Personal.Address address : addressList) { + if (address.getAddressTypeId().equals(addressTypeId)) + return address.getAddressLine1(); + } + return ""; } private Future getAddressTypeId(RequestContext requestContext) { diff --git a/src/test/java/org/folio/service/RoutingListServiceTest.java b/src/test/java/org/folio/service/RoutingListServiceTest.java index ae9e444c4..5014b6db8 100644 --- a/src/test/java/org/folio/service/RoutingListServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListServiceTest.java @@ -5,6 +5,7 @@ import static org.folio.TestUtils.getMockData; import static org.folio.rest.impl.MockServer.ROUTING_LIST_MOCK_DATA_PATH; import static org.folio.rest.impl.MockServer.USERS_MOCK_DATA_PATH; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; @@ -23,7 +24,6 @@ import org.folio.rest.core.models.RequestEntry; import org.folio.rest.jaxrs.model.RoutingList; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -61,7 +61,7 @@ void processTemplate(VertxTestContext vertxTestContext) throws IOException { var expectedTemplateRequest = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + "-expected-template-request.json")); var setting = new Setting().withId(UUID.randomUUID().toString()) .withKey("routing-list") - .withValue("93d3d88d-499b-45d0-9bc7-ac73c3a19880"); + .withValue("1c4b225f-f669-4e9b-afcd-ebc0e273a34e"); doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any()); doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any()); @@ -72,7 +72,7 @@ void processTemplate(VertxTestContext vertxTestContext) throws IOException { vertxTestContext.assertComplete(future) .onComplete(result -> { - Assertions.assertTrue(result.succeeded()); + assertTrue(result.succeeded()); vertxTestContext.completeNow(); }); } diff --git a/src/test/java/org/folio/service/UserServiceTest.java b/src/test/java/org/folio/service/UserServiceTest.java new file mode 100644 index 000000000..33e0ce7f3 --- /dev/null +++ b/src/test/java/org/folio/service/UserServiceTest.java @@ -0,0 +1,65 @@ +package org.folio.service; + +import static io.vertx.core.Future.succeededFuture; +import static org.folio.TestUtils.getMockData; +import static org.folio.rest.impl.MockServer.USERS_MOCK_DATA_PATH; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; + +import java.io.IOException; +import java.util.List; + +import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; +import io.vertx.junit5.VertxExtension; +import io.vertx.junit5.VertxTestContext; +import org.folio.models.UserCollection; +import org.folio.rest.core.RestClient; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.core.models.RequestEntry; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@ExtendWith(VertxExtension.class) +public class UserServiceTest { + + @Mock + private RestClient restClient; + @InjectMocks + private UserService userService; + @Mock + private RequestContext requestContextMock; + private AutoCloseable mockitoMocks; + + @BeforeEach + public void initMocks() throws Exception { + mockitoMocks = MockitoAnnotations.openMocks(this); + } + + @AfterEach + void afterEach() throws Exception { + mockitoMocks.close(); + } + + @Test + void getUsersByIds(VertxTestContext vertxTestContext) throws IOException { + var users = new JsonObject(getMockData(USERS_MOCK_DATA_PATH + "user_collection.json")).mapTo(UserCollection.class); + List userIds = users.getUsers().stream().map(user -> String.valueOf(user.getId())).toList(); + doReturn(succeededFuture(users)).when(restClient).get(any(RequestEntry.class), eq(UserCollection.class), any()); + + Future future = userService.getUsersByIds(userIds, requestContextMock); + + vertxTestContext.assertComplete(future) + .onComplete(result -> { + assertTrue(result.succeeded()); + vertxTestContext.completeNow(); + }); + } +} diff --git a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json index f5beed65a..4863165c3 100644 --- a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json +++ b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8-expected-template-request.json @@ -1,17 +1,24 @@ { - "templateId" : "9465105a-e8a1-470c-9817-142d33bc4fcd", - "lang" : "en", - "outputFormat" : "text/html", - "context" : { - "routingList" : { - "name" : "Mars expedition", - "notes" : "Future note", + "templateId": "9465105a-e8a1-470c-9817-142d33bc4fcd", + "lang": "en", + "outputFormat": "text/html", + "context": { + "routingList": { + "name": "Mars expedition", + "notes": "Future note", "userIds": [] }, - "users" : [ { - "lastName" : "Denesik", - "firstName" : "Maiya", - "routingAddress" : "17691 Rodriguez Divide" - } ] + "users": [ + { + "lastName": "Denesik", + "firstName": "Maiya", + "routingAddress": "144 Law" + }, + { + "lastName": "Huels", + "firstName": "Lois", + "routingAddress": "123 Law" + } + ] } } diff --git a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json index e172458bb..358a9642f 100644 --- a/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json +++ b/src/test/resources/mockdata/routingLists/eee951de-ea49-400a-96e8-705ae5a1e1e8.json @@ -4,8 +4,8 @@ "name": "Mars expedition", "notes": "Future note", "userIds": [ - "d926d900-e27d-46d6-bba8-31e9d5c2cf44", - "077274ad-6b4f-4c28-9779-6d381e7a1ca1" + "00bc2807-4d5b-4a27-a2b5-b7b1ba431cc4", + "011dc219-6b7f-4d93-ae7f-f512ed651493" ], "poLineId": "8343e5a0-fed8-11e8-8eb2-f2801f1b9fd1" } diff --git a/src/test/resources/mockdata/users/user_collection.json b/src/test/resources/mockdata/users/user_collection.json index e6d1ebb3e..5a0b7aa23 100644 --- a/src/test/resources/mockdata/users/user_collection.json +++ b/src/test/resources/mockdata/users/user_collection.json @@ -1,47 +1,108 @@ { - "users" : [ { - "username" : "sallie", - "id" : "00bc2807-4d5b-4a27-a2b5-b7b1ba431cc4", - "barcode" : "133143370961512", - "active" : false, - "type" : "patron", - "patronGroup" : "503a81cd-6c26-400f-b620-14c08943697c", - "departments" : [ ], - "proxyFor" : [ ], - "personal" : { - "lastName" : "Denesik", - "firstName" : "Maiya", - "middleName" : "Noel", - "email" : "ahmad@kertzmann-bailey-and-brekke.io", - "phone" : "759.693.8557", - "mobilePhone" : "(557)093-7575", - "dateOfBirth" : "2009-07-21T00:00:00.000+00:00", - "addresses" : [ { - "countryId" : "US", - "addressLine1" : "17691 Rodriguez Divide", - "city" : "Birmingham", - "region" : "CO", - "postalCode" : "85748", - "addressTypeId" : "93d3d88d-499b-45d0-9bc7-ac73c3a19880", - "primaryAddress" : true - } ], - "preferredContactTypeId" : "002" + "users": [ + { + "username": "sallie", + "id": "00bc2807-4d5b-4a27-a2b5-b7b1ba431cc4", + "barcode": "133143370961512", + "active": false, + "type": "patron", + "patronGroup": "503a81cd-6c26-400f-b620-14c08943697c", + "departments": [], + "proxyFor": [], + "personal": { + "lastName": "Denesik", + "firstName": "Maiya", + "middleName": "Noel", + "email": "ahmad@kertzmann-bailey-and-brekke.io", + "phone": "759.693.8557", + "mobilePhone": "(557)093-7575", + "dateOfBirth": "2009-07-21T00:00:00.000+00:00", + "addresses": [ + { + "countryId": "US", + "addressLine1": "17691 Rodriguez Divide", + "city": "Birmingham", + "region": "CO", + "postalCode": "85748", + "addressTypeId": "93d3d88d-499b-45d0-9bc7-ac73c3a19880", + "primaryAddress": true + }, + { + "city": "", + "region": "", + "countryId": "US", + "postalCode": "", + "addressLine1": "144 Law", + "addressTypeId": "1c4b225f-f669-4e9b-afcd-ebc0e273a34e", + "primaryAddress": false + } + ], + "preferredContactTypeId": "002" + }, + "enrollmentDate": "2015-04-13T00:00:00.000+00:00", + "expirationDate": "2019-06-20T00:00:00.000+00:00", + "createdDate": "2024-01-28T16:01:21.650+00:00", + "updatedDate": "2024-01-28T16:01:21.650+00:00", + "metadata": { + "createdDate": "2024-01-28T16:01:21.601+00:00", + "createdByUserId": "631fdcc3-c7c6-48e6-b51c-8a727c5d3dd7", + "updatedDate": "2024-01-28T16:01:21.601+00:00", + "updatedByUserId": "631fdcc3-c7c6-48e6-b51c-8a727c5d3dd7" + } }, - "enrollmentDate" : "2015-04-13T00:00:00.000+00:00", - "expirationDate" : "2019-06-20T00:00:00.000+00:00", - "createdDate" : "2024-01-28T16:01:21.650+00:00", - "updatedDate" : "2024-01-28T16:01:21.650+00:00", - "metadata" : { - "createdDate" : "2024-01-28T16:01:21.601+00:00", - "createdByUserId" : "631fdcc3-c7c6-48e6-b51c-8a727c5d3dd7", - "updatedDate" : "2024-01-28T16:01:21.601+00:00", - "updatedByUserId" : "631fdcc3-c7c6-48e6-b51c-8a727c5d3dd7" + { + "id": "011dc219-6b7f-4d93-ae7f-f512ed651493", + "type": "patron", + "active": false, + "barcode": "897083256223023", + "metadata": { + "createdDate": "2024-01-28T15:51:44.463Z", + "updatedDate": "2024-01-28T15:51:44.463Z", + "createdByUserId": "631fdcc3-c7c6-48e6-b51c-8a727c5d3dd7", + "updatedByUserId": "631fdcc3-c7c6-48e6-b51c-8a727c5d3dd7" + }, + "personal": { + "email": "monserrat@donnelly-skiles.ge", + "phone": "(619)645-7533 x5934", + "firstName": "Lois", + "lastName": "Huels", + "addresses": [ + { + "city": "Marana", + "region": "NH", + "countryId": "US", + "postalCode": "02013-0332", + "addressLine1": "69175 Haley Skyway", + "addressTypeId": "93d3d88d-499b-45d0-9bc7-ac73c3a19880", + "primaryAddress": true + }, + { + "city": "", + "region": "", + "countryId": "US", + "postalCode": "", + "addressLine1": "123 Law", + "addressTypeId": "1c4b225f-f669-4e9b-afcd-ebc0e273a34e", + "primaryAddress": false + } + ], + "dateOfBirth": "1947-06-23T00:00:00.000+00:00", + "preferredContactTypeId": "004" + }, + "proxyFor": [], + "username": "elmer", + "createdDate": "2024-01-28T15:51:44.505+00:00", + "departments": [], + "patronGroup": "3684a786-6671-4268-8ed0-9db82ebca60b", + "updatedDate": "2024-01-28T15:51:44.505+00:00", + "enrollmentDate": "2018-05-06T00:00:00.000+00:00", + "expirationDate": "2019-09-02T00:00:00.000+00:00" } - } ], - "totalRecords" : 1, - "resultInfo" : { - "totalRecords" : 1, - "facets" : [ ], - "diagnostics" : [ ] + ], + "totalRecords": 2, + "resultInfo": { + "totalRecords": 2, + "facets": [], + "diagnostics": [] } } From 61f892f3adc5b918fc060accd3cd4dc94496b129 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 4 Apr 2024 12:24:35 +0500 Subject: [PATCH 30/35] [MODORSERS-1026] - added userService test --- src/test/java/org/folio/ApiTestSuite.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/org/folio/ApiTestSuite.java b/src/test/java/org/folio/ApiTestSuite.java index 3b2c44d9c..f0dac243e 100644 --- a/src/test/java/org/folio/ApiTestSuite.java +++ b/src/test/java/org/folio/ApiTestSuite.java @@ -44,6 +44,7 @@ import org.folio.service.ReasonForClosureServiceTest; import org.folio.service.SuffixServiceTest; import org.folio.service.TagServiceTest; +import org.folio.service.UserServiceTest; import org.folio.service.consortium.SharingInstanceServiceTest; import org.folio.service.exchange.ManualExchangeRateProviderTest; import org.folio.service.expenceclass.ExpenseClassValidationServiceTest; @@ -480,4 +481,8 @@ class TagServiceTestNested extends TagServiceTest { @Nested class RoutingListServiceTestNested extends RoutingListServiceTest { } + + @Nested + class UserServiceTestNested extends UserServiceTest { + } } From adfc40c7ec966cf4170a81301ce243efc40aff17 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 4 Apr 2024 15:56:11 +0500 Subject: [PATCH 31/35] [MODORSERS-1026] - Fixed Setting api --- src/main/java/org/folio/orders/utils/ResourcePathResolver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java index 01613131d..4e29b8e7a 100644 --- a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java +++ b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java @@ -92,7 +92,7 @@ private ResourcePathResolver() { apis.put(EXPORT_HISTORY, "/orders-storage/export-history"); apis.put(TAGS, "/tags"); apis.put(USERS, "/users"); - apis.put(ORDER_SETTINGS, "/order-storage/settings"); + apis.put(ORDER_SETTINGS, "/orders-storage/settings"); apis.put(ROUTING_LISTS, "/orders-storage/routing-lists"); SUB_OBJECT_COLLECTION_APIS = Collections.unmodifiableMap(apis); From c3a9f9591b4e371735f53c3b6ce3848b6a3f446d Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 4 Apr 2024 16:57:18 +0500 Subject: [PATCH 32/35] [MODORSERS-1026] - Fix the setting api --- .../org/folio/service/RoutingListService.java | 19 ++++++++++++------- .../folio/service/RoutingListServiceTest.java | 5 ++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/folio/service/RoutingListService.java b/src/main/java/org/folio/service/RoutingListService.java index 3e6b23d53..cf6ce1211 100644 --- a/src/main/java/org/folio/service/RoutingListService.java +++ b/src/main/java/org/folio/service/RoutingListService.java @@ -18,7 +18,7 @@ import org.apache.logging.log4j.Logger; import org.folio.models.TemplateProcessingRequest; import org.folio.models.UserCollection; -import org.folio.rest.acq.model.Setting; +import org.folio.rest.acq.model.SettingCollection; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; @@ -102,21 +102,26 @@ private List fillUsersForContext(UserCollection private String getUserAddress(List addressList, String addressTypeId) { for (UserCollection.User.Personal.Address address : addressList) { - if (address.getAddressTypeId().equals(addressTypeId)) + if (address.getAddressTypeId().equals(addressTypeId)) { + log.info("getUserAddress:: Required address with addressTypeId={} is found", addressTypeId); return address.getAddressLine1(); + } } + log.warn("getUserAddress:: Required address is not found with addressTypId={}", addressTypeId); return ""; } private Future getAddressTypeId(RequestContext requestContext) { var requestEntry = new RequestEntry(ORDER_SETTINGS_ENDPOINT) .withQuery("key=" + ROUTING_USER_ADDRESS_TYPE_ID); - return restClient.get(requestEntry, Setting.class, requestContext) - .map(setting -> { - if (ObjectUtils.isEmpty(setting) || StringUtils.isBlank(setting.getValue())) { - throw new ResourceNotFoundException("Setting is not found for addressTypeId"); + return restClient.get(requestEntry, SettingCollection.class, requestContext) + .map(settingCollection -> { + var settings = settingCollection.getSettings(); + if (ObjectUtils.isEmpty(settings) || StringUtils.isBlank(settings.get(0).getValue())) { + log.error("getAddressTypeId:: Setting is not found with key={}", ROUTING_USER_ADDRESS_TYPE_ID); + throw new ResourceNotFoundException("Setting is not found with key={}", ROUTING_USER_ADDRESS_TYPE_ID); } - return setting.getValue(); + return settings.get(0).getValue(); }); } diff --git a/src/test/java/org/folio/service/RoutingListServiceTest.java b/src/test/java/org/folio/service/RoutingListServiceTest.java index 5014b6db8..f55759bc0 100644 --- a/src/test/java/org/folio/service/RoutingListServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListServiceTest.java @@ -11,6 +11,7 @@ import static org.mockito.Mockito.doReturn; import java.io.IOException; +import java.util.List; import java.util.UUID; import io.vertx.core.Future; @@ -19,6 +20,7 @@ import io.vertx.junit5.VertxTestContext; import org.folio.models.UserCollection; import org.folio.rest.acq.model.Setting; +import org.folio.rest.acq.model.SettingCollection; import org.folio.rest.core.RestClient; import org.folio.rest.core.models.RequestContext; import org.folio.rest.core.models.RequestEntry; @@ -62,10 +64,11 @@ void processTemplate(VertxTestContext vertxTestContext) throws IOException { var setting = new Setting().withId(UUID.randomUUID().toString()) .withKey("routing-list") .withValue("1c4b225f-f669-4e9b-afcd-ebc0e273a34e"); + var settingCollection = new SettingCollection().withSettings(List.of(setting)); doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any()); doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any()); - doReturn(succeededFuture(setting)).when(restClient).get(any(RequestEntry.class), eq(Setting.class), any()); + doReturn(succeededFuture(settingCollection)).when(restClient).get(any(RequestEntry.class), eq(SettingCollection.class), any()); doReturn(succeededFuture(new JsonObject())).when(restClient).postJsonObject(any(RequestEntry.class), eq(expectedTemplateRequest), any()); Future future = routingListService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); From 1298d3b4ff4c2fb78b67c3a1fa583f6da4512955 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 4 Apr 2024 17:29:54 +0500 Subject: [PATCH 33/35] [MODORSERS-1026] - Increased unit test --- .../org/folio/service/RoutingListService.java | 2 +- .../folio/service/RoutingListServiceTest.java | 25 +++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/folio/service/RoutingListService.java b/src/main/java/org/folio/service/RoutingListService.java index cf6ce1211..08c189c3e 100644 --- a/src/main/java/org/folio/service/RoutingListService.java +++ b/src/main/java/org/folio/service/RoutingListService.java @@ -119,7 +119,7 @@ private Future getAddressTypeId(RequestContext requestContext) { var settings = settingCollection.getSettings(); if (ObjectUtils.isEmpty(settings) || StringUtils.isBlank(settings.get(0).getValue())) { log.error("getAddressTypeId:: Setting is not found with key={}", ROUTING_USER_ADDRESS_TYPE_ID); - throw new ResourceNotFoundException("Setting is not found with key={}", ROUTING_USER_ADDRESS_TYPE_ID); + throw new ResourceNotFoundException(String.format("Setting is not found with key=%s", ROUTING_USER_ADDRESS_TYPE_ID)); } return settings.get(0).getValue(); }); diff --git a/src/test/java/org/folio/service/RoutingListServiceTest.java b/src/test/java/org/folio/service/RoutingListServiceTest.java index f55759bc0..0cd392acb 100644 --- a/src/test/java/org/folio/service/RoutingListServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListServiceTest.java @@ -11,6 +11,7 @@ import static org.mockito.Mockito.doReturn; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -73,10 +74,30 @@ void processTemplate(VertxTestContext vertxTestContext) throws IOException { Future future = routingListService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); - vertxTestContext.assertComplete(future) - .onComplete(result -> { + vertxTestContext.assertComplete(future).onComplete(result -> { assertTrue(result.succeeded()); vertxTestContext.completeNow(); }); } + + @Test + void throwErrorWhenSettingNotFound(VertxTestContext vertxTestContext) throws IOException { + var routingList = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + ".json")).mapTo(RoutingList.class); + var users = new JsonObject(getMockData(USERS_MOCK_DATA_PATH + "user_collection.json")).mapTo(UserCollection.class); + var expectedTemplateRequest = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + "-expected-template-request.json")); + + doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any()); + doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any()); + doReturn(succeededFuture(new SettingCollection().withSettings(new ArrayList<>()))) + .when(restClient).get(any(RequestEntry.class), eq(SettingCollection.class), any()); + + Future future = routingListService.processTemplateRequest(ROUTING_LIST_ID, requestContextMock); + + vertxTestContext.assertFailure(future).onComplete(result -> { + assertTrue(result.failed()); + var exception = result.cause().getMessage(); + assertTrue(exception.contains("Setting is not found with key=ROUTING_USER_ADDRESS_TYPE_ID")); + vertxTestContext.completeNow(); + }); + } } From 9837b1b13abd562b63d198d3b2f32130810d5763 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 4 Apr 2024 17:30:14 +0500 Subject: [PATCH 34/35] [MODORSERS-1026] - Increased unit test --- src/test/java/org/folio/service/RoutingListServiceTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/org/folio/service/RoutingListServiceTest.java b/src/test/java/org/folio/service/RoutingListServiceTest.java index 0cd392acb..fe9651a93 100644 --- a/src/test/java/org/folio/service/RoutingListServiceTest.java +++ b/src/test/java/org/folio/service/RoutingListServiceTest.java @@ -84,7 +84,6 @@ void processTemplate(VertxTestContext vertxTestContext) throws IOException { void throwErrorWhenSettingNotFound(VertxTestContext vertxTestContext) throws IOException { var routingList = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + ".json")).mapTo(RoutingList.class); var users = new JsonObject(getMockData(USERS_MOCK_DATA_PATH + "user_collection.json")).mapTo(UserCollection.class); - var expectedTemplateRequest = new JsonObject(getMockData(ROUTING_LIST_MOCK_DATA_PATH + ROUTING_LIST_ID + "-expected-template-request.json")); doReturn(succeededFuture(routingList)).when(restClient).get(any(RequestEntry.class), eq(RoutingList.class), any()); doReturn(succeededFuture(users)).when(userService).getUsersByIds(eq(routingList.getUserIds()), any()); From d86faff13ad9e6922760f31381f59a98c76e46b0 Mon Sep 17 00:00:00 2001 From: Azizbek Khushvakov Date: Thu, 4 Apr 2024 17:41:37 +0500 Subject: [PATCH 35/35] [MODORSERS-1026] - Reformat code --- .../org/folio/service/RoutingListService.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/folio/service/RoutingListService.java b/src/main/java/org/folio/service/RoutingListService.java index 08c189c3e..8c9b92b9e 100644 --- a/src/main/java/org/folio/service/RoutingListService.java +++ b/src/main/java/org/folio/service/RoutingListService.java @@ -62,6 +62,20 @@ private Future getUsersAndCreateTemplate(RoutingList .map(users -> createTemplateRequest(routingList, users, addressTypId))); } + private Future getAddressTypeId(RequestContext requestContext) { + var requestEntry = new RequestEntry(ORDER_SETTINGS_ENDPOINT) + .withQuery("key=" + ROUTING_USER_ADDRESS_TYPE_ID); + return restClient.get(requestEntry, SettingCollection.class, requestContext) + .map(settingCollection -> { + var settings = settingCollection.getSettings(); + if (ObjectUtils.isEmpty(settings) || StringUtils.isBlank(settings.get(0).getValue())) { + log.error("getAddressTypeId:: Setting is not found with key={}", ROUTING_USER_ADDRESS_TYPE_ID); + throw new ResourceNotFoundException(String.format("Setting is not found with key=%s", ROUTING_USER_ADDRESS_TYPE_ID)); + } + return settings.get(0).getValue(); + }); + } + private TemplateProcessingRequest createTemplateRequest(RoutingList routingList, UserCollection users, String addressTypeId) { var templateRequest = createBaseTemplateRequest(); templateRequest.withContext(new TemplateProcessingRequest.Context() @@ -111,20 +125,6 @@ private String getUserAddress(List address return ""; } - private Future getAddressTypeId(RequestContext requestContext) { - var requestEntry = new RequestEntry(ORDER_SETTINGS_ENDPOINT) - .withQuery("key=" + ROUTING_USER_ADDRESS_TYPE_ID); - return restClient.get(requestEntry, SettingCollection.class, requestContext) - .map(settingCollection -> { - var settings = settingCollection.getSettings(); - if (ObjectUtils.isEmpty(settings) || StringUtils.isBlank(settings.get(0).getValue())) { - log.error("getAddressTypeId:: Setting is not found with key={}", ROUTING_USER_ADDRESS_TYPE_ID); - throw new ResourceNotFoundException(String.format("Setting is not found with key=%s", ROUTING_USER_ADDRESS_TYPE_ID)); - } - return settings.get(0).getValue(); - }); - } - private RoutingList fillRoutingListForContext(RoutingList routingList) { return new RoutingList() .withName(routingList.getName())