From 65197efe262cbb0c92b766769e8dc0c1b3e8f706 Mon Sep 17 00:00:00 2001 From: Boburbek Kadirkhodjaev Date: Mon, 9 Dec 2024 21:45:53 +0500 Subject: [PATCH] [MODORDERS-1209]. Implement API to Send claims for multiple pieces (#1054) * [MODORDERS-1209]. Implement API to Send claims for multiple pieces * [MODORDERS-1209]. Update acq-models & add descriptors * [MODORDERS-1209]. Update service with latest acq-models changes * [MODORDERS-1209]. Add API tests, clean MockServer * [MODORDERS-1209]. Improve claiming result output * [MODORDERS-1209]. Remove logging * [MODORDERS-1209]. Temporary change export type, add logging * [MODORDERS-1209]. Remove temporary change export type, change return results, fix tests * [MODORDERS-1209]. Add sleep 1000 * [MODORDERS-1209]. Change test log level * [MODORDERS-1209]. Fix failing handleGetPieces * [MODORDERS-1209]. Add missing pieceRecord to mockData * [MODORDERS-1209]. Fix handleGetPieceById method * [MODORDERS-1209]. Fix handleGetPieces * [MODORDERS-1209]. Revert handleGetPieces & add try-catch * [MODORDERS-1209]. Remove try-catch, change piece status validation * [MODORDERS-1209]. Update piece mockData with Late status * [MODORDERS-1209]. Update piece status validation * [MODORDERS-1209]. Add more logs * [MODORDERS-1209]. Add more logs * [MODORDERS-1209]. Remove piece from mockData piece collections * [MODORDERS-1209]. Add more logging * [MODORDERS-1209]. Add claimPieceIds to job integration details * [MODORDERS-1209]. Add more logs * [MODORDERS-1209]. Fix MockServer handleGetPieces from interfering * [MODORDERS-1209]. Revert getPiecesByIds * [MODORDERS-1209]. Update tests * [MODORDERS-1209]. Fix sonar * [MODORDERS-1209]. Apply review recommendations * [MODORDERS-1209]. Fix descriptors * [MODORDERS-1209]. Add claimedPieceIds assertion to job creation * [MODORDERS-1209]. Add unit tests, add ClaimingError enum * [MODORDERS-1209]. Fix minor typos * [MODORDERS-1209]. Update descriptors * [MODORDERS-1209]. Remove redundant message * [MODORDERS-1209]. Change log level * [MODORDERS-1209]. Remove old logs, change arg name * [MODORDERS-1209]. Fix sonar issue, change log level * [MODORDERS-1209]. Remove CANNOT_COMPLETE_REQ from onComplete --- descriptors/ModuleDescriptor-template.json | 46 +- ramls/claim.raml | 39 ++ .../folio/models/claiming/ClaimingError.java | 17 + .../claiming/IntegrationDetailField.java | 14 + .../org/folio/orders/utils/HelperUtils.java | 1 + .../orders/utils/ResourcePathResolver.java | 9 +- .../folio/rest/impl/PiecesClaimingApi.java | 46 ++ .../service/pieces/PieceStorageService.java | 10 +- .../service/pieces/PiecesClaimingService.java | 232 ++++++++++ src/test/java/org/folio/ApiTestSuite.java | 9 + src/test/java/org/folio/RestTestUtils.java | 12 +- src/test/java/org/folio/TestConstants.java | 3 + .../ReceiptStatusConsistencyTest.java | 4 +- .../rest/impl/CheckinReceivingApiTest.java | 38 +- .../java/org/folio/rest/impl/MockServer.java | 425 ++++++++---------- .../org/folio/rest/impl/PieceApiTest.java | 6 +- .../rest/impl/PiecesClaimingApiTest.java | 227 ++++++++++ .../pieces/PiecesClaimingServiceTest.java | 295 ++++++++++++ src/test/resources/log4j2-test.properties | 6 +- .../send-claims-1-piece-1-vendor-1-job.json | 5 + .../test_diku_limit_10_claims.json | 94 ++++ .../428c60e8-c43d-4543-b0d4-36dada430e51.json | 60 +++ .../mockdata/lines/po_line_collection.json | 62 ++- .../mockdata/organizations/organizations.json | 139 ++++++ ...-dcd0ba36-b660-4751-b9fe-c8ac61ff6f99.json | 13 + .../pieces/pieceRecordsCollection.json | 15 +- 26 files changed, 1546 insertions(+), 281 deletions(-) create mode 100644 ramls/claim.raml create mode 100644 src/main/java/org/folio/models/claiming/ClaimingError.java create mode 100644 src/main/java/org/folio/models/claiming/IntegrationDetailField.java create mode 100644 src/main/java/org/folio/rest/impl/PiecesClaimingApi.java create mode 100644 src/main/java/org/folio/service/pieces/PiecesClaimingService.java create mode 100644 src/test/java/org/folio/rest/impl/PiecesClaimingApiTest.java create mode 100644 src/test/java/org/folio/service/pieces/PiecesClaimingServiceTest.java create mode 100644 src/test/resources/mockdata/claiming/send-claims-1-piece-1-vendor-1-job.json create mode 100644 src/test/resources/mockdata/configurations.entries/test_diku_limit_10_claims.json create mode 100644 src/test/resources/mockdata/lines/428c60e8-c43d-4543-b0d4-36dada430e51.json create mode 100644 src/test/resources/mockdata/organizations/organizations.json create mode 100644 src/test/resources/mockdata/pieces/pieceRecord-dcd0ba36-b660-4751-b9fe-c8ac61ff6f99.json diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 175a06ef3..f472ce55d 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -1179,6 +1179,31 @@ } ] }, + { + "id": "pieces.send-claims", + "version": "1.0", + "handlers": [ + { + "methods": ["POST"], + "pathPattern": "/pieces/claim", + "permissionsRequired": [ + "pieces.send-claims.collection.post" + ], + "modulePermissions": [ + "configuration.entries.collection.get", + "orders-storage.pieces.collection.get", + "orders-storage.pieces.item.put", + "orders-storage.po-lines.item.get", + "orders-storage.po-lines.item.put", + "orders-storage.purchase-orders.item.get", + "orders-storage.titles.item.get", + "organizations-storage.organizations.item.get", + "data-export.job.item.post", + "data-export.job.send.item.execute" + ] + } + ] + }, { "id": "_jsonSchemas", "version": "1.0", @@ -1421,6 +1446,10 @@ { "id": "consortia", "version": "1.0" + }, + { + "id": "data-export-spring", + "version": "2.0" } ], "permissionSets": [ @@ -1993,7 +2022,19 @@ "orders.bind-pieces.item.delete" ] }, - + { + "permissionName": "pieces.send-claims.collection.post", + "displayName" : "send-claims collection post", + "description" : "Send claims collection post" + }, + { + "permissionName": "pieces.send-claims.all", + "displayName": "All send claims perms", + "description": "All permissions for the send claims", + "subPermissions": [ + "pieces.send-claims.collection.post" + ] + }, { "permissionName": "orders.all", "displayName": "orders - all permissions", @@ -2030,7 +2071,8 @@ "orders.acquisition-methods.all", "orders.export-history.all", "orders.routing-lists.all", - "orders.bind-pieces.all" + "orders.bind-pieces.all", + "pieces.send-claims.all" ] }, { diff --git a/ramls/claim.raml b/ramls/claim.raml new file mode 100644 index 000000000..cccced5ea --- /dev/null +++ b/ramls/claim.raml @@ -0,0 +1,39 @@ +#%RAML 1.0 +title: Claim +baseUri: https://github.com/folio-org/mod-orders +version: v1 +protocols: [ HTTP, HTTPS ] + +documentation: + - title: Pieces Business Logic API + content: API for claiming pieces + +types: + claiming-collection: !include acq-models/mod-orders/schemas/claimingCollection.json + claiming-results: !include acq-models/mod-orders/schemas/claimingResults.json + errors: !include raml-util/schemas/errors.schema + 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: + validate: !include raml-util/traits/validation.raml + +resourceTypes: + post-with-200: !include rtypes/post-json-200.raml + +/pieces/claim: + displayName: Claim pieces + description: | + Claim pieces. The endpoint is used to: + - Claims pieces grouped by organizations + - Triggers jobs in mod-data-export per each organization that contains an integration detail + type: + post-with-200: + requestSchema: claiming-collection + responseSchema: claiming-results + requestExample: !include acq-models/mod-orders/examples/claimingCollection.sample + responseExample: !include acq-models/mod-orders/examples/claimingResults.sample + is: [validate] + post: + description: Claim pieces diff --git a/src/main/java/org/folio/models/claiming/ClaimingError.java b/src/main/java/org/folio/models/claiming/ClaimingError.java new file mode 100644 index 000000000..4f5c8ab5e --- /dev/null +++ b/src/main/java/org/folio/models/claiming/ClaimingError.java @@ -0,0 +1,17 @@ +package org.folio.models.claiming; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ClaimingError { + CANNOT_SEND_CLAIMS_PIECE_IDS_ARE_EMPTY("Cannot send claims, piece ids are empty"), + CANNOT_FIND_PIECES_WITH_LATE_STATUS_TO_PROCESS("Cannot find pieces with LATE status to process"), + CANNOT_RETRIEVE_CONFIG_ENTRIES("Cannot retrieve config entries"), + CANNOT_GROUP_PIECES_BY_VENDOR_MESSAGE("Cannot group pieces by vendor"), + CANNOT_CREATE_JOBS_AND_UPDATE_PIECES("Cannot create jobs and update pieces"), + CANNOT_FIND_A_PIECE_BY_ID("Cannot find a piece by '%s' id"); + + private final String value; +} diff --git a/src/main/java/org/folio/models/claiming/IntegrationDetailField.java b/src/main/java/org/folio/models/claiming/IntegrationDetailField.java new file mode 100644 index 000000000..bf75daa7d --- /dev/null +++ b/src/main/java/org/folio/models/claiming/IntegrationDetailField.java @@ -0,0 +1,14 @@ +package org.folio.models.claiming; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum IntegrationDetailField { + EXPORT_TYPE_SPECIFIC_PARAMETERS("exportTypeSpecificParameters"), + VENDOR_EDI_ORDERS_EXPORT_CONFIG("vendorEdiOrdersExportConfig"), + CLAIM_PIECE_IDS("claimPieceIds"); + + private final String value; +} diff --git a/src/main/java/org/folio/orders/utils/HelperUtils.java b/src/main/java/org/folio/orders/utils/HelperUtils.java index aea701b2a..a12b3bd1c 100644 --- a/src/main/java/org/folio/orders/utils/HelperUtils.java +++ b/src/main/java/org/folio/orders/utils/HelperUtils.java @@ -65,6 +65,7 @@ public class HelperUtils { public static final String SYSTEM_CONFIG_MODULE_NAME = "ORG"; public static final String ORDER_CONFIG_MODULE_NAME = "ORDERS"; + public static final String DATA_EXPORT_SPRING_CONFIG_MODULE_NAME = "mod-data-export-spring"; public static final String DEFAULT_POLINE_LIMIT = "1"; public static final String REASON_COMPLETE = "Complete"; diff --git a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java index cb03de7b2..aa8e91a94 100644 --- a/src/main/java/org/folio/orders/utils/ResourcePathResolver.java +++ b/src/main/java/org/folio/orders/utils/ResourcePathResolver.java @@ -14,6 +14,7 @@ private ResourcePathResolver() { public static final String PO_LINES_BATCH_STORAGE = "poLines.batch"; public static final String PO_LINES_BUSINESS = "poLinesBusinessEndpoint"; public static final String ORDERS_BUSINESS = "ordersBusinessEndpoint"; + public static final String PIECES_CLAIMING_BUSINESS = "piecesClaimingBusinessEndpoint"; public static final String PO_NUMBER = "poNumber"; public static final String VENDOR_ID = "vendor"; public static final String PO_LINE_NUMBER = "poLineNumber"; @@ -25,6 +26,7 @@ private ResourcePathResolver() { public static final String REPORTING_CODES = "reportingCodes"; public static final String PURCHASE_ORDER_STORAGE = "purchaseOrder"; public static final String PIECES_STORAGE = "pieces"; + public static final String ORGANIZATION_STORAGE = "organizations"; public static final String RECEIVING_HISTORY = "receiving-history"; public static final String RECEIPT_STATUS = "receiptStatus"; public static final String PAYMENT_STATUS = "paymentStatus"; @@ -56,7 +58,8 @@ private ResourcePathResolver() { public static final String ORDER_SETTINGS = "orderSettings"; public static final String USERS = "users"; public static final String CONSORTIA_USER_TENANTS = "consortia.user-tenants"; - + public static final String DATA_EXPORT_SPRING_CREATE_JOB = "data-export-spring.job"; + public static final String DATA_EXPORT_SPRING_EXECUTE_JOB = "data-export-spring.send-job"; private static final Map SUB_OBJECT_ITEM_APIS; private static final Map SUB_OBJECT_COLLECTION_APIS; @@ -72,9 +75,11 @@ private ResourcePathResolver() { apis.put(PO_LINES_BATCH_STORAGE, "/orders-storage/po-lines-batch"); apis.put(PO_LINES_BUSINESS, "/orders/order-lines"); apis.put(ORDERS_BUSINESS, "/orders/composite-orders"); + apis.put(PIECES_CLAIMING_BUSINESS, "/pieces/claim"); apis.put(PO_NUMBER, "/orders-storage/po-number"); apis.put(PURCHASE_ORDER_STORAGE, "/orders-storage/purchase-orders"); apis.put(PIECES_STORAGE, "/orders-storage/pieces"); + apis.put(ORGANIZATION_STORAGE, "/organizations-storage/organizations"); 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"); @@ -105,6 +110,8 @@ private ResourcePathResolver() { apis.put(CONSORTIA_USER_TENANTS, "/consortia/{id}/user-tenants"); apis.put(ORDER_SETTINGS, "/orders-storage/settings"); apis.put(ROUTING_LISTS, "/orders-storage/routing-lists"); + apis.put(DATA_EXPORT_SPRING_CREATE_JOB, "/data-export-spring/jobs"); + apis.put(DATA_EXPORT_SPRING_EXECUTE_JOB, "/data-export-spring/jobs/send"); SUB_OBJECT_COLLECTION_APIS = Collections.unmodifiableMap(apis); SUB_OBJECT_ITEM_APIS = Collections.unmodifiableMap( diff --git a/src/main/java/org/folio/rest/impl/PiecesClaimingApi.java b/src/main/java/org/folio/rest/impl/PiecesClaimingApi.java new file mode 100644 index 000000000..ccf26a1d4 --- /dev/null +++ b/src/main/java/org/folio/rest/impl/PiecesClaimingApi.java @@ -0,0 +1,46 @@ +package org.folio.rest.impl; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Context; +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.core.Vertx; +import org.folio.rest.annotations.Validate; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.jaxrs.model.ClaimingCollection; +import org.folio.rest.jaxrs.resource.PiecesClaim; +import org.folio.service.pieces.PiecesClaimingService; +import org.folio.spring.SpringContextUtil; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.ws.rs.core.Response; +import java.util.Map; + +import static org.folio.orders.utils.ResourcePathResolver.PIECES_CLAIMING_BUSINESS; +import static org.folio.orders.utils.ResourcePathResolver.resourceByIdPath; +import static org.folio.rest.RestConstants.OKAPI_URL; + +public class PiecesClaimingApi extends BaseApi implements PiecesClaim { + + @Autowired + private PiecesClaimingService pieceClaimingService; + + public PiecesClaimingApi() { + SpringContextUtil.autowireDependencies(this, Vertx.currentContext()); + } + + @Override + @Validate + public void postPiecesClaim(ClaimingCollection claimingCollection, Map okapiHeaders, + Handler> asyncResultHandler, Context vertxContext) { + var requestContext = new RequestContext(vertxContext, okapiHeaders); + pieceClaimingService.sendClaims(claimingCollection, requestContext) + .onSuccess(claimingResults -> { + var okapiUrl = okapiHeaders.get(OKAPI_URL); + var url = resourceByIdPath(PIECES_CLAIMING_BUSINESS); + var response = buildResponseWithLocation(okapiUrl, url, claimingResults); + asyncResultHandler.handle(Future.succeededFuture(response)); + }) + .onFailure(t -> handleErrorResponse(asyncResultHandler, t)); + } +} diff --git a/src/main/java/org/folio/service/pieces/PieceStorageService.java b/src/main/java/org/folio/service/pieces/PieceStorageService.java index b89a19eb2..466cab229 100644 --- a/src/main/java/org/folio/service/pieces/PieceStorageService.java +++ b/src/main/java/org/folio/service/pieces/PieceStorageService.java @@ -13,7 +13,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import lombok.extern.log4j.Log4j2; import org.apache.commons.collections4.CollectionUtils; @@ -135,6 +134,7 @@ public Future getAllPieces(String query, RequestContext request } public Future getAllPieces(int limit, int offset, String query, RequestContext requestContext) { + log.debug("getAllPieces:: limit: {}, offset: {}, query: {}", limit, offset, query); var requestEntry = new RequestEntry(PIECE_STORAGE_ENDPOINT).withQuery(query).withOffset(offset).withLimit(limit); return restClient.get(requestEntry, PieceCollection.class, requestContext); } @@ -165,20 +165,18 @@ public Future> getPiecesByIds(List pieceIds, RequestContext .map(PieceCollection::getPieces) .flatMap(Collection::stream) .toList()) - .onSuccess(v -> log.info("getPiecesByIds:: pieces by ids successfully retrieve: {}", pieceIds)); + .onSuccess(v -> log.info("getPiecesByIds:: pieces by ids successfully retrieve: {}", pieceIds)) + .onFailure(t -> log.error("Failed to get pieces by ids", t)); } public Future> getPiecesByLineIdsByChunks(List lineIds, RequestContext requestContext) { - log.info("getPiecesByLineIdsByChunks start"); var futures = ofSubLists(new ArrayList<>(lineIds), MAX_IDS_FOR_GET_RQ_15) .map(ids -> getPieceChunkByLineIds(ids, requestContext)) .toList(); return collectResultsOnSuccess(futures) .map(lists -> lists.stream() .flatMap(Collection::stream) - .collect(Collectors.toList())) - .onSuccess(v -> log.info("getPiecesByLineIdsByChunks end")); - + .toList()); } private Future> getPieceChunkByLineIds(Collection poLineIds, RequestContext requestContext) { diff --git a/src/main/java/org/folio/service/pieces/PiecesClaimingService.java b/src/main/java/org/folio/service/pieces/PiecesClaimingService.java new file mode 100644 index 000000000..a2fdcf561 --- /dev/null +++ b/src/main/java/org/folio/service/pieces/PiecesClaimingService.java @@ -0,0 +1,232 @@ +package org.folio.service.pieces; + +import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import one.util.streamex.StreamEx; +import org.apache.commons.lang3.tuple.Pair; +import org.folio.rest.core.RestClient; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.jaxrs.model.ClaimingCollection; +import org.folio.rest.jaxrs.model.ClaimingPieceResult; +import org.folio.rest.jaxrs.model.ClaimingResults; +import org.folio.rest.jaxrs.model.Error; +import org.folio.rest.jaxrs.model.Piece; +import org.folio.rest.jaxrs.model.PieceBatchStatusCollection; +import org.folio.service.caches.ConfigurationEntriesCache; +import org.folio.service.orders.PurchaseOrderLineService; +import org.folio.service.orders.PurchaseOrderStorageService; +import org.folio.service.organization.OrganizationService; +import org.folio.service.pieces.flows.update.PieceUpdateFlowManager; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Objects; + +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toList; +import static org.folio.models.claiming.ClaimingError.CANNOT_CREATE_JOBS_AND_UPDATE_PIECES; +import static org.folio.models.claiming.ClaimingError.CANNOT_FIND_A_PIECE_BY_ID; +import static org.folio.models.claiming.ClaimingError.CANNOT_FIND_PIECES_WITH_LATE_STATUS_TO_PROCESS; +import static org.folio.models.claiming.ClaimingError.CANNOT_GROUP_PIECES_BY_VENDOR_MESSAGE; +import static org.folio.models.claiming.ClaimingError.CANNOT_RETRIEVE_CONFIG_ENTRIES; +import static org.folio.models.claiming.ClaimingError.CANNOT_SEND_CLAIMS_PIECE_IDS_ARE_EMPTY; +import static org.folio.models.claiming.IntegrationDetailField.CLAIM_PIECE_IDS; +import static org.folio.models.claiming.IntegrationDetailField.EXPORT_TYPE_SPECIFIC_PARAMETERS; +import static org.folio.models.claiming.IntegrationDetailField.VENDOR_EDI_ORDERS_EXPORT_CONFIG; +import static org.folio.orders.utils.HelperUtils.DATA_EXPORT_SPRING_CONFIG_MODULE_NAME; +import static org.folio.orders.utils.HelperUtils.collectResultsOnSuccess; +import static org.folio.orders.utils.ResourcePathResolver.DATA_EXPORT_SPRING_CREATE_JOB; +import static org.folio.orders.utils.ResourcePathResolver.DATA_EXPORT_SPRING_EXECUTE_JOB; +import static org.folio.orders.utils.ResourcePathResolver.resourcesPath; +import static org.folio.rest.jaxrs.model.ClaimingPieceResult.Status.FAILURE; +import static org.folio.rest.jaxrs.model.ClaimingPieceResult.Status.SUCCESS; + +@Log4j2 +@Service +@RequiredArgsConstructor +public class PiecesClaimingService { + + private static final String JOB_STATUS = "status"; + private static final String EXPORT_TYPE_CLAIMS = "CLAIMS"; + + private final ConfigurationEntriesCache configurationEntriesCache; + private final PieceStorageService pieceStorageService; + private final PurchaseOrderLineService purchaseOrderLineService; + private final PurchaseOrderStorageService purchaseOrderStorageService; + private final OrganizationService organizationService; + private final PieceUpdateFlowManager pieceUpdateFlowManager; + private final RestClient restClient; + + /** + * Sends claims by receiving pieces to be claimed, groups them by vendor, + * updates piece statuses and finally creates jobs per vendor and associated integration details + * @param claimingCollection An array of pieces ids + * @param requestContext Headers to make HTTP or Kafka requests + * @return Future of an array of claimingResults + */ + public Future sendClaims(ClaimingCollection claimingCollection, RequestContext requestContext) { + if (CollectionUtils.isEmpty(claimingCollection.getClaimingPieceIds())) { + log.info("sendClaims:: No claims are sent, claiming piece ids are empty"); + return Future.succeededFuture(createEmptyClaimingResults(CANNOT_SEND_CLAIMS_PIECE_IDS_ARE_EMPTY.getValue())); + } + return configurationEntriesCache.loadConfiguration(DATA_EXPORT_SPRING_CONFIG_MODULE_NAME, requestContext) + .compose(config -> { + if (CollectionUtils.isEmpty(config.getMap())) { + log.info("sendClaims:: No claims are sent, config has no entries"); + return Future.succeededFuture(createEmptyClaimingResults(CANNOT_RETRIEVE_CONFIG_ENTRIES.getValue())); + } + var pieceIds = claimingCollection.getClaimingPieceIds().stream().toList(); + log.info("sendClaims:: Received pieces to be claimed, pieceIds: {}", pieceIds); + return groupPieceIdsByVendorId(pieceIds, requestContext) + .compose(pieceIdsByVendorIds -> { + if (CollectionUtils.isEmpty(pieceIdsByVendorIds)) { + return Future.succeededFuture(createEmptyClaimingResults(CANNOT_FIND_PIECES_WITH_LATE_STATUS_TO_PROCESS.getValue())); + } + log.info("sendClaims:: Using pieces by vendor id map, map: {}", pieceIdsByVendorIds); + return createJobsByVendor(config, pieceIdsByVendorIds, requestContext); + }); + }) + .onFailure(t -> log.error("sendClaims:: Failed send claims: {}", JsonObject.mapFrom(claimingCollection).encodePrettily(), t)); + } + + private Future>> groupPieceIdsByVendorId(List pieceIds, RequestContext requestContext) { + log.info("groupPieceIdsByVendorId:: Grouping pieces by vendor, pieceIds count: {}", pieceIds.size()); + return pieceStorageService.getPiecesByIds(pieceIds, requestContext) + .compose(pieces -> { + if (CollectionUtils.isEmpty(pieces)) { + log.info("groupPieceIdsByVendorId:: No pieces are found by piece ids, pieceIds: {}", pieceIds); + return Future.succeededFuture(); + } + var uniquePiecePoLinePairs = pieces.stream() + .filter(Objects::nonNull).filter(piece -> Objects.nonNull(piece.getId()) && Objects.nonNull(piece.getPoLineId())) + .map(piece -> Pair.of(piece.getPoLineId(), piece.getId())).distinct() + .toList(); + log.info("groupPieceIdsByVendorId:: Prepared unique piece-poLine pairs, pairs: {}", uniquePiecePoLinePairs); + return collectResultsOnSuccess(createPieceIdByVendorFutures(pieces, uniquePiecePoLinePairs, requestContext)) + .map(PiecesClaimingService::transformAndGroupPieceIdsByVendorId); + }); + } + + private List>> createPieceIdByVendorFutures(List pieces, List> uniquePiecePoLinePairs, + RequestContext requestContext) { + var pieceIdByVendorIdFutures = new ArrayList>>(); + uniquePiecePoLinePairs.forEach(piecePoLinePairs -> { + var foundPiece = pieces.stream() + .filter(Objects::nonNull).filter(piece -> Objects.nonNull(piece.getId())).filter(piece -> piece.getId().equals(piecePoLinePairs.getRight())) + .findFirst().orElseThrow(() -> new NoSuchElementException(String.format(CANNOT_FIND_A_PIECE_BY_ID.getValue(), piecePoLinePairs.getRight()))); + var pieceIdByVendorIdFuture = createVendorPiecePair(piecePoLinePairs, foundPiece, requestContext); + if (Objects.nonNull(pieceIdByVendorIdFuture)) { + pieceIdByVendorIdFutures.add(pieceIdByVendorIdFuture); + } + }); + return pieceIdByVendorIdFutures; + } + + private Future> createVendorPiecePair(Pair piecePoLinePairs, + Piece piece, RequestContext requestContext) { + if (!piece.getReceivingStatus().equals(Piece.ReceivingStatus.LATE)) { + log.info("createVendorPiecePair:: Ignoring processing of a piece not in LATE state, piece id: {}", piece.getId()); + return Future.succeededFuture(); + } + return purchaseOrderLineService.getOrderLineById(piecePoLinePairs.getLeft(), requestContext) + .compose(poLine -> purchaseOrderStorageService.getPurchaseOrderById(poLine.getPurchaseOrderId(), requestContext) + .compose(purchaseOrder -> organizationService.getVendorById(purchaseOrder.getVendor(), requestContext))) + .map(vendor -> { + if (Objects.nonNull(vendor) && Boolean.TRUE.equals(vendor.getIsVendor())) { + return Pair.of(vendor.getId(), piecePoLinePairs.getRight()); + } + return null; + }); + } + + private static Map> transformAndGroupPieceIdsByVendorId(List> piecesByVendorList) { + return StreamEx.of(piecesByVendorList).distinct().filter(Objects::nonNull) + .groupingBy(Pair::getKey, mapping(Pair::getValue, toList())); + } + + private Future createJobsByVendor(JsonObject config, Map> pieceIdsByVendorId, + RequestContext requestContext) { + log.info("createJobsByVendor:: Creating jobs by vendor, vendors by pieces count: {}", pieceIdsByVendorId.size()); + if (CollectionUtils.isEmpty(pieceIdsByVendorId)) { + log.info("createJobsByVendor:: No jobs are created, pieceIdsByVendorId is empty"); + return Future.succeededFuture(new ClaimingResults() + .withClaimingPieceResults(createErrorClaimingResults(pieceIdsByVendorId, CANNOT_GROUP_PIECES_BY_VENDOR_MESSAGE.getValue()))); + } + return collectResultsOnSuccess(createUpdatePiecesAndJobFutures(config, pieceIdsByVendorId, requestContext)) + .map(updatedPieceLists -> { + if (CollectionUtils.isEmpty(updatedPieceLists)) { + log.info("createJobsByVendor:: No pieces were processed for claiming"); + return new ClaimingResults().withClaimingPieceResults(createErrorClaimingResults(pieceIdsByVendorId, CANNOT_CREATE_JOBS_AND_UPDATE_PIECES.getValue())); + } + var successClaimingPieceResults = createSuccessClaimingResults(updatedPieceLists); + log.info("createJobsByVendor:: Successfully processed pieces for claiming, count: {}", successClaimingPieceResults.size()); + var claimingResults = new ClaimingResults().withClaimingPieceResults(successClaimingPieceResults); + log.debug("createJobsByVendor:: Returning claiming results, claimingResults: {}", JsonObject.mapFrom(claimingResults).encodePrettily()); + return claimingResults; + }); + } + + private List>> createUpdatePiecesAndJobFutures(JsonObject config, Map> pieceIdsByVendorId, + RequestContext requestContext) { + var updatePiecesAndJobFutures = new ArrayList>>(); + pieceIdsByVendorId.forEach((vendorId, pieceIds) -> config.stream() + .filter(pieceIdsByVendorIdEntry -> isExportTypeClaimsAndCorrectVendorId(vendorId, pieceIdsByVendorIdEntry) + && Objects.nonNull(pieceIdsByVendorIdEntry.getValue())) + .forEach(pieceIdsByVendorIdEntry -> { + log.info("createJobsByVendor:: Preparing job integration detail for vendor, vendor id: {}, pieces: {}, job key: {}", + vendorId, pieceIds.size(), pieceIdsByVendorIdEntry.getKey()); + updatePiecesAndJobFutures.add(updatePiecesAndCreateJob(pieceIds, pieceIdsByVendorIdEntry, requestContext)); + })); + return updatePiecesAndJobFutures; + } + + private static ClaimingResults createEmptyClaimingResults(String message) { + return new ClaimingResults().withClaimingPieceResults(List.of(new ClaimingPieceResult().withError(new Error().withMessage(message)))); + } + + private List createSuccessClaimingResults(List> updatedPieceLists) { + return updatedPieceLists.stream().flatMap(Collection::stream).distinct() + .map(pieceId -> new ClaimingPieceResult().withPieceId(pieceId).withStatus(SUCCESS)) + .toList(); + } + + private List createErrorClaimingResults(Map> pieceIdsByVendorId, String message) { + return pieceIdsByVendorId.values().stream() + .flatMap(Collection::stream) + .map(pieceId -> new ClaimingPieceResult().withPieceId(pieceId).withStatus(FAILURE).withError(new Error().withMessage(message))) + .toList(); + } + + private static boolean isExportTypeClaimsAndCorrectVendorId(String vendorId, Map.Entry pieceIdsByVendorIdEntry) { + return pieceIdsByVendorIdEntry.getKey().startsWith(String.format("%s_%s", EXPORT_TYPE_CLAIMS, vendorId)); + } + + private Future> updatePiecesAndCreateJob(List pieceIds, Map.Entry pieceIdsByVendorIdEntry, + RequestContext requestContext) { + log.info("updatePiecesAndCreateJob:: Updating pieces and creating a job, job key: {}, count: {}", pieceIdsByVendorIdEntry.getKey(), pieceIds.size()); + return pieceUpdateFlowManager.updatePiecesStatuses(pieceIds, PieceBatchStatusCollection.ReceivingStatus.CLAIM_SENT, requestContext) + .compose(v -> createJob(pieceIdsByVendorIdEntry.getKey(), pieceIdsByVendorIdEntry.getValue(), pieceIds, requestContext).map(pieceIds)); + } + + private Future createJob(String configKey, Object configValue, List pieceIds, RequestContext requestContext) { + var integrationDetail = new JsonObject(String.valueOf(configValue)); + integrationDetail.getJsonObject(EXPORT_TYPE_SPECIFIC_PARAMETERS.getValue()) + .getJsonObject(VENDOR_EDI_ORDERS_EXPORT_CONFIG.getValue()) + .put(CLAIM_PIECE_IDS.getValue(), pieceIds); + return restClient.post(resourcesPath(DATA_EXPORT_SPRING_CREATE_JOB), integrationDetail, Object.class, requestContext) + .compose(response -> { + var createdJob = new JsonObject(String.valueOf(response)); + log.info("createJob:: Created job, config key: {}, job status: {}", configKey, createdJob.getString(JOB_STATUS)); + return restClient.postEmptyResponse(resourcesPath(DATA_EXPORT_SPRING_EXECUTE_JOB), createdJob, requestContext) + .onSuccess(v -> log.info("createJob:: Executed job, config key: {}", configKey)); + }) + .mapEmpty(); + } +} diff --git a/src/test/java/org/folio/ApiTestSuite.java b/src/test/java/org/folio/ApiTestSuite.java index 526b4fef8..8f1d9f8da 100644 --- a/src/test/java/org/folio/ApiTestSuite.java +++ b/src/test/java/org/folio/ApiTestSuite.java @@ -32,6 +32,7 @@ import org.folio.rest.impl.HoldingsSummaryAPITest; import org.folio.rest.impl.OrderTemplateTest; import org.folio.rest.impl.PieceApiTest; +import org.folio.rest.impl.PiecesClaimingApiTest; import org.folio.rest.impl.PoNumberApiTest; import org.folio.rest.impl.PurchaseOrderLinesApiTest; import org.folio.rest.impl.PurchaseOrdersApiTest; @@ -96,6 +97,7 @@ import org.folio.service.pieces.PieceServiceTest; import org.folio.service.pieces.PieceStorageServiceTest; import org.folio.service.pieces.PieceUpdateInventoryServiceTest; +import org.folio.service.pieces.PiecesClaimingServiceTest; import org.folio.service.pieces.flows.BasePieceFlowHolderBuilderTest; import org.folio.service.pieces.flows.DefaultPieceFlowsValidatorTest; import org.folio.service.pieces.flows.create.PieceCreateFlowInventoryManagerTest; @@ -546,4 +548,11 @@ class FinanceHoldersBuilderTestNested extends FinanceHoldersBuilderTest { class SettingsRetrieverTestNested extends SettingsRetrieverTest { } + @Nested + class PiecesClaimingApiTestNested extends PiecesClaimingApiTest { + } + + @Nested + class PiecesClaimingServiceNested extends PiecesClaimingServiceTest { + } } diff --git a/src/test/java/org/folio/RestTestUtils.java b/src/test/java/org/folio/RestTestUtils.java index 49bbfcd32..292ccd411 100644 --- a/src/test/java/org/folio/RestTestUtils.java +++ b/src/test/java/org/folio/RestTestUtils.java @@ -6,6 +6,7 @@ import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10; import static org.folio.TestConstants.NON_EXIST_CONFIG_X_OKAPI_TENANT; import static org.folio.TestConstants.ORDERS_CHECKIN_ENDPOINT; +import static org.folio.TestConstants.PIECES_CLAIMING_ENDPOINT; import static org.folio.TestConstants.ORDERS_RECEIVING_ENDPOINT; import static org.folio.TestConstants.X_OKAPI_TOKEN; import static org.folio.TestUtils.getModifiedProtectedFields; @@ -51,8 +52,10 @@ public static Response verifyPostResponse(String url, String body, Headers heade .extract() .response(); - // Verify no messages sent via event bus on POST (except receiving/check-in) - if (!(url.startsWith(ORDERS_RECEIVING_ENDPOINT) || url.startsWith(ORDERS_CHECKIN_ENDPOINT))) { + // Verify no messages sent via event bus on POST (except receiving/check-in/claiming) + if (!(url.startsWith(ORDERS_RECEIVING_ENDPOINT) + || url.startsWith(ORDERS_CHECKIN_ENDPOINT) + || url.startsWith(PIECES_CLAIMING_ENDPOINT))) { HandlersTestHelper.verifyOrderStatusUpdateEvent(0); } @@ -86,7 +89,6 @@ public static Response verifyPostResponseWithQueryParams(String url, String body return response; } - public static Response verifyPut(String url, JsonObject body, String expectedContentType, int expectedCode) { return verifyPut(url, body.encodePrettily(), expectedContentType, expectedCode); } @@ -226,8 +228,4 @@ public static void checkPreventProtectedFieldsModificationRule(String path, Json public static Headers prepareHeaders(Header... headers) { return new Headers(headers); } - - public static String buildQueryParam(String query) { - return "?query=" + query; - } } diff --git a/src/test/java/org/folio/TestConstants.java b/src/test/java/org/folio/TestConstants.java index 9c485021a..d258b7b7a 100644 --- a/src/test/java/org/folio/TestConstants.java +++ b/src/test/java/org/folio/TestConstants.java @@ -22,6 +22,7 @@ private TestConstants() {} public static final String ORDERS_EXPECT_ENDPOINT = "/orders/expect"; public static final String ORDERS_BIND_ENDPOINT = "/orders/bind-pieces"; public static final String ORDERS_BIND_ID_ENDPOINT = "/orders/bind-pieces/%s"; + public static final String PIECES_CLAIMING_ENDPOINT = "/pieces/claim"; public static final String PO_LINE_NUMBER_VALUE = "1"; public static final String BAD_QUERY = "unprocessableQuery"; @@ -60,6 +61,7 @@ private TestConstants() {} public static final String NON_EXIST_HOLDINGS_SOURCE_TENANT = "nonExistHoldingsSource"; public static final String COMPOSITE_PO_LINES_PREFIX = "compositePoLines[0]."; public static final String OKAPI_URL = "X-Okapi-Url"; + public static final String OKAPI_TENANT = "X-Okapi-Tenant"; public static final Header INSTANCE_TYPE_CONTAINS_CODE_AS_INSTANCE_STATUS_TENANT_HEADER = new Header(OKAPI_HEADER_TENANT, INSTANCE_TYPE_CONTAINS_CODE_AS_INSTANCE_STATUS_TENANT); public static final Header NON_EXIST_INSTANCE_STATUS_TENANT_HEADER = new Header(OKAPI_HEADER_TENANT, NON_EXIST_INSTANCE_STATUS_TENANT); @@ -71,6 +73,7 @@ private TestConstants() {} 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"); + public static final Header EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10_CLAIMS = new Header(OKAPI_HEADER_TENANT, "test_diku_limit_10_claims"); public static final Header EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_1 = new Header(OKAPI_HEADER_TENANT, "test_diku_limit_1"); public static final Header EXIST_CONFIG_X_OKAPI_TENANT_ECS = new Header(OKAPI_HEADER_TENANT, "consortium"); public static final Header INVALID_CONFIG_X_OKAPI_TENANT = new Header(OKAPI_HEADER_TENANT, "invalid_config"); diff --git a/src/test/java/org/folio/orders/events/handlers/ReceiptStatusConsistencyTest.java b/src/test/java/org/folio/orders/events/handlers/ReceiptStatusConsistencyTest.java index aa2ac5a03..00d6cd192 100644 --- a/src/test/java/org/folio/orders/events/handlers/ReceiptStatusConsistencyTest.java +++ b/src/test/java/org/folio/orders/events/handlers/ReceiptStatusConsistencyTest.java @@ -5,8 +5,8 @@ import static org.folio.TestConfig.isVerticleNotDeployed; import static org.folio.TestUtils.checkVertxContextCompletion; import static org.folio.TestUtils.getMockAsJson; +import static org.folio.rest.impl.MockServer.PO_LINES_COLLECTION; import static org.folio.orders.events.utils.EventUtils.POL_UPDATE_FIELD; -import static org.folio.rest.impl.MockServer.POLINES_COLLECTION; import static org.folio.rest.impl.MockServer.PO_LINES_MOCK_DATA_PATH; import static org.folio.rest.impl.MockServer.getPieceSearches; import static org.folio.rest.impl.MockServer.getPoLineSearches; @@ -129,7 +129,7 @@ void testSuccessReceiptStatusWhenReceiptStatusBetweenPiecesAndPoLineNotConsisten void testSuccessPartiallyReceivedStatusWhenAtleastOneSuccessfullyReceivedPiece(VertxTestContext context) throws Throwable { logger.info("=== Test case to verify partially received status when at least one successfully received piece ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(5).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(5).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); sendEvent(createBody(POLINE_UUID_TIED_TO_PIECE_PARTIALLY_RECEIVED), context.succeeding(result -> { diff --git a/src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java b/src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java index 684656bf7..847f1ffd1 100644 --- a/src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java +++ b/src/test/java/org/folio/rest/impl/CheckinReceivingApiTest.java @@ -108,7 +108,7 @@ import static org.folio.rest.impl.MockServer.CONSISTENT_ECS_PURCHASE_ORDER_ID_PHYSICAL_MULTIPLE_ITEMS; import static org.folio.rest.impl.MockServer.CONSISTENT_ECS_PURCHASE_ORDER_ID_PHYSICAL_SINGLE_ITEM; import static org.folio.rest.impl.MockServer.PIECE_RECORDS_MOCK_DATA_PATH; -import static org.folio.rest.impl.MockServer.POLINES_COLLECTION; +import static org.folio.rest.impl.MockServer.PO_LINES_COLLECTION; import static org.folio.rest.impl.MockServer.addMockEntry; import static org.folio.rest.impl.MockServer.addMockTitles; import static org.folio.rest.impl.MockServer.getCreatedHoldings; @@ -186,7 +186,7 @@ static void after() { void testPostCheckInElectronicWithNoItems() { logger.info("=== Test POST Checkin - CheckIn Electronic resource"); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(7).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(7).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); CheckinCollection checkInRq = getMockAsJson(CHECKIN_RQ_MOCK_DATA_PATH + "checkin-pe-mix-2-electronic-resources.json").mapTo(CheckinCollection.class); @@ -234,7 +234,7 @@ void testPostCheckInElectronicWithNoItems() { void testPostCheckInPhysicalWithMissingItem() { logger.info("=== Test POST Checkin - CheckIn physical resource with only one item updated"); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(7).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(7).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); CheckinCollection checkInRq = getMockAsJson(CHECKIN_RQ_MOCK_DATA_PATH + "checkin-pe-mix-2-physical-resources.json").mapTo(CheckinCollection.class); @@ -307,7 +307,7 @@ void testPostCheckInPhysicalWithMissingItem() { void testPostCheckinRevertPhysicalResource() { logger.info("=== Test POST Check-in - Revert received Physical resource"); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(8).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(8).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); CheckinCollection checkinReq = getMockAsJson( @@ -364,7 +364,7 @@ void testPostCheckinRevertPhysicalResource() { void testReceiveOngoingOrderWithChangedLocation() { logger.info("=== Test POST Receive - Ongoing PO Lines"); - CompositePoLine originalPoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(9).mapTo(CompositePoLine.class); + CompositePoLine originalPoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(9).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(originalPoLine)); ReceivingCollection receivingRq = getMockAsJson(RECEIVING_RQ_MOCK_DATA_PATH + "receive-physical-ongoing.json").mapTo(ReceivingCollection.class); @@ -413,7 +413,7 @@ void testReceiveOngoingOrderWithChangedLocation() { void testReceiveCancelledOrderWithChangedLocation() { logger.info("=== Test POST Receive - Cancelled PO Lines"); - CompositePoLine originalPoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(10).mapTo(CompositePoLine.class); + CompositePoLine originalPoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(10).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(originalPoLine)); ReceivingCollection receivingRq = getMockAsJson(RECEIVING_RQ_MOCK_DATA_PATH + "receive-physical-cancelled.json").mapTo(ReceivingCollection.class); @@ -465,7 +465,7 @@ void testPostCheckInLocationId() { String poLineId = "fe47e95d-24e9-4a9a-9dc0-bcba64b51f56"; String pieceId = UUID.randomUUID().toString(); - CompositePoLine poLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(5).mapTo(CompositePoLine.class); + CompositePoLine poLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(5).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(poLine)); List toBeCheckedInList = new ArrayList<>(); @@ -532,7 +532,7 @@ void testPostCheckInLocationId() { void testPostReceivingPhysicalAll() { logger.info("=== Test POST Receiving - Receive physical resources ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(2).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(2).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); ReceivingCollection receivingRq = getMockAsJson(RECEIVING_RQ_MOCK_DATA_PATH + "receive-physical-all-resources.json").mapTo(ReceivingCollection.class); @@ -646,7 +646,7 @@ void testPostCheckinElectronicPhysicalChangeLocationIdNewHoldingIsCreatedForPhys void testPostCheckInPhysicalFullyReceivedWithChangedLocation() { logger.info("=== Test POST check-in - Check-in Fully Received physical resource with changed location ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(11).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(11).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); CheckinCollection checkinCollection = getMockAsJson(CHECKIN_RQ_MOCK_DATA_PATH + "checkin-fully-receive-physical-resource.json").mapTo(CheckinCollection.class); @@ -704,7 +704,7 @@ void testPostCheckInPhysicalFullyReceivedWithChangedLocation() { void testPostReceivePhysicalCancelledOrder() { logger.info("=== Test POST Receive - Check-in Fully Received physical resource with cancelled order ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(14).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(14).mapTo(CompositePoLine.class); CompositePurchaseOrder compositePurchaseOrder = new CompositePurchaseOrder().withId(compositePoLine.getPurchaseOrderId()).withWorkflowStatus(CompositePurchaseOrder.WorkflowStatus.CLOSED); addMockEntry(PURCHASE_ORDER_STORAGE, compositePurchaseOrder); addMockEntry(PO_LINES_STORAGE, compositePoLine); @@ -774,7 +774,7 @@ private static Stream testPostReceivePhysicalCancelledOrderLineArgs() void testPostReceivePhysicalCancelledOrderLine(int fileIdx, int poLineIdx, PoLine.PaymentStatus paymentStatus, PoLine.ReceiptStatus receiptStatus) { logger.info("=== Test POST Receive - Check-in Fully Received physical resource with cancelled order line ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(poLineIdx).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(poLineIdx).mapTo(CompositePoLine.class); CompositePurchaseOrder compositePurchaseOrder = new CompositePurchaseOrder().withId(compositePoLine.getPurchaseOrderId()).withWorkflowStatus(CompositePurchaseOrder.WorkflowStatus.OPEN); addMockEntry(PURCHASE_ORDER_STORAGE, compositePurchaseOrder); addMockEntry(PO_LINES_STORAGE, compositePoLine); @@ -838,7 +838,7 @@ void testPostReceivePhysicalCancelledOrderLine(int fileIdx, int poLineIdx, PoLin void testPostCheckInPhysicalFullyReceivedCancelledOrder() { logger.info("=== Test POST check-in - Check-in Fully Received physical resource with cancelled order ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(14).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(14).mapTo(CompositePoLine.class); CompositePurchaseOrder compositePurchaseOrder = new CompositePurchaseOrder().withId(compositePoLine.getPurchaseOrderId()).withWorkflowStatus(CompositePurchaseOrder.WorkflowStatus.CLOSED); addMockEntry(PURCHASE_ORDER_STORAGE, compositePurchaseOrder); addMockEntry(PO_LINES_STORAGE, compositePoLine); @@ -918,7 +918,7 @@ private static Stream testPostCheckInPhysicalFullyReceivedCancelledOr void testPostCheckInPhysicalFullyReceivedCancelledOrderLine(int fileIdx, int poLineIdx, PoLine.PaymentStatus paymentStatus, PoLine.ReceiptStatus receiptStatus) { logger.info("=== Test POST check-in - Check-in Fully Received physical resource with cancelled order line ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(poLineIdx).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(poLineIdx).mapTo(CompositePoLine.class); CompositePurchaseOrder compositePurchaseOrder = new CompositePurchaseOrder().withId(compositePoLine.getPurchaseOrderId()).withWorkflowStatus(CompositePurchaseOrder.WorkflowStatus.OPEN); addMockEntry(PURCHASE_ORDER_STORAGE, compositePurchaseOrder); addMockEntry(PO_LINES_STORAGE, compositePoLine); @@ -1002,7 +1002,7 @@ void testPostCheckInPhysicalFullyReceivedEcs(String orderId, String checkInColle CompositePurchaseOrder purchaseOrder = new CompositePurchaseOrder().withId(orderId).withWorkflowStatus(CompositePurchaseOrder.WorkflowStatus.OPEN); addMockEntry(PURCHASE_ORDER_STORAGE, purchaseOrder); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines") + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines") .stream() .map(json -> (JsonObject) json) .filter(json -> json.getString("purchaseOrderId").equals(purchaseOrder.getId())) @@ -1302,7 +1302,7 @@ void testPostCheckinTitleNotFoundError() { void testPostReceivingElectronicPartially() { logger.info("=== Test POST Receiving - Receive partially electronic resources"); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(4).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(4).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); // 10 pieces in total with PoLineId daa9cfd1-b330-4b65-8c2a-3663aaae5130 @@ -1358,7 +1358,7 @@ void testPostReceivingPhysicalWithErrors() throws IOException { logger.info("=== Test POST Receiving - Receive physical resources with different errors"); ReceivingCollection receivingRq = getMockAsJson(RECEIVING_RQ_MOCK_DATA_PATH + "receive-physical-resources-6-of-10-with-errors.json").mapTo(ReceivingCollection.class); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(3).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(3).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); ReceivingResults results = verifyPostResponse(ORDERS_RECEIVING_ENDPOINT, JsonObject.mapFrom(receivingRq).encode(), prepareHeaders(EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10), APPLICATION_JSON, 200).as(ReceivingResults.class); @@ -1467,7 +1467,7 @@ void testMovePieceStatusFromUnreceivableToExpected() { private void verifyProperQuantityOfHoldingsCreated(ReceivingCollection receivingRq) throws IOException { // get processed poline - PoLineCollection poLineCollection = new JsonObject(getMockData(POLINES_COLLECTION)).mapTo(PoLineCollection.class); + PoLineCollection poLineCollection = new JsonObject(getMockData(PO_LINES_COLLECTION)).mapTo(PoLineCollection.class); // get processed pieces for receiving PieceCollection pieces = new JsonObject(getMockData(PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecordsCollection.json")) @@ -1945,7 +1945,7 @@ void testPostReceivingWithErrorSearchingForItem() { void testPostReceivingRevertMixedResources() { logger.info("=== Test POST Receiving - Revert received P/E Mix resources"); - CompositePoLine poLines = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(5).mapTo(CompositePoLine.class); + CompositePoLine poLines = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(5).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(poLines)); ReceivingCollection receivingRq = getMockAsJson(RECEIVING_RQ_MOCK_DATA_PATH + "revert-pe-mix-4-of-5-resources.json").mapTo(ReceivingCollection.class); @@ -2001,7 +2001,7 @@ void testPostReceivingRevertMixedResources() { void testPostReceivingRevertElectronicResource() { logger.info("=== Test POST Receiving - Revert received electronic resource"); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(6).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(6).mapTo(CompositePoLine.class); MockServer.addMockOrderData(Collections.singletonList(compositePoLine)); ReceivingCollection receivingRq = getMockAsJson(RECEIVING_RQ_MOCK_DATA_PATH + "revert-electronic-1-of-1-resource.json").mapTo(ReceivingCollection.class); diff --git a/src/test/java/org/folio/rest/impl/MockServer.java b/src/test/java/org/folio/rest/impl/MockServer.java index b9798b653..fa2d2073a 100644 --- a/src/test/java/org/folio/rest/impl/MockServer.java +++ b/src/test/java/org/folio/rest/impl/MockServer.java @@ -17,6 +17,7 @@ import static org.folio.TestConstants.EMPTY_CONFIG_TENANT; import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_1; import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10; +import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10_CLAIMS; import static org.folio.TestConstants.ID; import static org.folio.TestConstants.ID_BAD_FORMAT; import static org.folio.TestConstants.ID_DOES_NOT_EXIST; @@ -37,6 +38,7 @@ import static org.folio.TestConstants.NON_EXIST_INSTANCE_TYPE_TENANT_HEADER; import static org.folio.TestConstants.NON_EXIST_LOAN_TYPE_TENANT; import static org.folio.TestConstants.NON_EXIST_LOAN_TYPE_TENANT_HEADER; +import static org.folio.TestConstants.OKAPI_TENANT; import static org.folio.TestConstants.PO_ID_GET_LINES_INTERNAL_SERVER_ERROR; import static org.folio.TestConstants.PO_LINE_NUMBER_VALUE; import static org.folio.TestConstants.PROTECTED_READ_ONLY_TENANT; @@ -59,6 +61,8 @@ import static org.folio.orders.utils.ResourcePathResolver.ALERTS; import static org.folio.orders.utils.ResourcePathResolver.BUDGETS; import static org.folio.orders.utils.ResourcePathResolver.CURRENT_BUDGET; +import static org.folio.orders.utils.ResourcePathResolver.DATA_EXPORT_SPRING_CREATE_JOB; +import static org.folio.orders.utils.ResourcePathResolver.DATA_EXPORT_SPRING_EXECUTE_JOB; import static org.folio.orders.utils.ResourcePathResolver.EXPENSE_CLASSES_URL; import static org.folio.orders.utils.ResourcePathResolver.EXPORT_HISTORY; import static org.folio.orders.utils.ResourcePathResolver.FINANCE_BATCH_TRANSACTIONS; @@ -69,6 +73,7 @@ import static org.folio.orders.utils.ResourcePathResolver.LEDGER_FY_ROLLOVER_ERRORS; import static org.folio.orders.utils.ResourcePathResolver.ORDER_INVOICE_RELATIONSHIP; import static org.folio.orders.utils.ResourcePathResolver.ORDER_TEMPLATES; +import static org.folio.orders.utils.ResourcePathResolver.ORGANIZATION_STORAGE; import static org.folio.orders.utils.ResourcePathResolver.PIECES_STORAGE; import static org.folio.orders.utils.ResourcePathResolver.PO_LINES_BATCH_STORAGE; import static org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE; @@ -88,6 +93,7 @@ import static org.folio.orders.utils.ResourcePathResolver.resourceByIdPath; import static org.folio.orders.utils.ResourcePathResolver.resourcesPath; import static org.folio.rest.RestVerticle.OKAPI_HEADER_TENANT; +import static org.folio.rest.acq.model.Piece.ReceivingStatus.LATE; import static org.folio.rest.core.exceptions.ErrorCodes.BUDGET_IS_INACTIVE; import static org.folio.rest.core.exceptions.ErrorCodes.BUDGET_NOT_FOUND_FOR_TRANSACTION; import static org.folio.rest.core.exceptions.ErrorCodes.FUND_CANNOT_BE_PAID; @@ -257,7 +263,9 @@ public class MockServer { private static final String ORDER_TEMPLATES_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "orderTemplates/"; private static final String RECEIVING_HISTORY_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "receivingHistory/"; private static final String ORGANIZATIONS_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "organizations/"; - public static final String POLINES_COLLECTION = PO_LINES_MOCK_DATA_PATH + "po_line_collection.json"; + public static final String PO_LINES_COLLECTION = PO_LINES_MOCK_DATA_PATH + "po_line_collection.json"; + public static final String PIECES_COLLECTION = PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecordsCollection.json"; + public static final String ORGANIZATION_COLLECTION = ORGANIZATIONS_MOCK_DATA_PATH + "organizations.json"; private static final String IDENTIFIER_TYPES_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "identifierTypes/"; private static final String ITEM_REQUESTS_MOCK_DATA_PATH = BASE_MOCK_DATA_PATH + "itemRequests/"; public static final String ACQUISITIONS_UNITS_COLLECTION = ACQUISITIONS_UNITS_MOCK_DATA_PATH + "/units.json"; @@ -285,7 +293,6 @@ public class MockServer { public static final String ECS_UNIVERSITY_HOLDINGS_RECORD_JSON = BASE_MOCK_DATA_PATH + "ecs/%s/university_holdings_record.json"; public static final String ECS_UNIVERSITY_ITEM_JSON = BASE_MOCK_DATA_PATH + "ecs/%s/university_item.json"; - static final String HEADER_SERVER_ERROR = "X-Okapi-InternalServerError"; private static final String PENDING_VENDOR_ID = "160501b3-52dd-41ec-a0ce-17762e7a9b47"; static final String ORDER_ID_WITH_PO_LINES = "ab18897b-0e40-4f31-896b-9c9adc979a87"; private static final String PIECE_POLINE_CONSISTENT_RECEIPT_STATUS_ID = "7d0aa803-a659-49f0-8a95-968f277c87d7"; @@ -410,14 +417,22 @@ public static List getPurchaseOrderRetrievals() { return serverRqRs.get(PURCHASE_ORDER_STORAGE, HttpMethod.GET); } - public static List getPurchaseOrderCreations() { - return serverRqRs.get(PURCHASE_ORDER_STORAGE, HttpMethod.POST); - } - public static List getPurchaseOrderUpdates() { return serverRqRs.get(PURCHASE_ORDER_STORAGE, HttpMethod.PUT); } + public static List getOrganizationSearches() { + return serverRqRs.get(ORGANIZATION_STORAGE, HttpMethod.SEARCH); + } + + public static List getDataExportSpringJobCreations() { + return serverRqRs.get(DATA_EXPORT_SPRING_CREATE_JOB, HttpMethod.POST); + } + + public static List getDataExportSpringJobExecutions() { + return serverRqRs.get(DATA_EXPORT_SPRING_EXECUTE_JOB, HttpMethod.POST); + } + public static List getPieceUpdates() { return serverRqRs.get(PIECES_STORAGE, HttpMethod.PUT); } @@ -521,11 +536,6 @@ public static List getUpdatedTransactions() { .toList(); } - static List getBatchCalls() { - return Optional.ofNullable(serverRqRs.get(FINANCE_BATCH_TRANSACTIONS, HttpMethod.POST)) - .orElse(Collections.emptyList()); - } - private static List getCollectionRecords(List entries) { return entries.stream() .filter(json -> !json.containsKey(ID)) @@ -558,7 +568,7 @@ private Optional getMockEntry(String objName, String id) { } private Optional> getMockEntries(String objName, Class tClass) { - List entryList = getRqRsEntries(HttpMethod.SEARCH, objName).stream() + List entryList = getRqRsEntries(HttpMethod.SEARCH, objName).stream() .map(entries -> entries.mapTo(tClass)) .collect(toList()); return Optional.ofNullable(entryList.isEmpty() ? null : entryList); @@ -575,8 +585,8 @@ public static List getRqRsEntries(HttpMethod method, String objName) private Router defineRoutes() { Router router = Router.router(vertx); - router.route().handler(BodyHandler.create()); + // POST router.post(resourcesPath(PURCHASE_ORDER_STORAGE)).handler(this::handlePostPurchaseOrder); router.post("/inventory/instances").handler(this::handlePostInstanceRecord); router.post("/item-storage/items").handler(this::handlePostItemStorRecord); @@ -589,7 +599,6 @@ private Router defineRoutes() { router.post(resourcesPath(FINANCE_BATCH_TRANSACTIONS)).handler(this::handleBatchTransactions); router.post(resourcesPath(TITLES)).handler(ctx -> handlePostGenericSubObj(ctx, TITLES)); router.post(resourcesPath(ROUTING_LISTS)).handler(ctx -> handlePostGenericSubObj(ctx, ROUTING_LISTS)); - router.post(resourcesPath(ACQUISITIONS_UNITS)).handler(ctx -> handlePostGenericSubObj(ctx, ACQUISITIONS_UNITS)); router.post(resourcesPath(ACQUISITION_METHODS)).handler(ctx -> handlePostGenericSubObj(ctx, ACQUISITION_METHODS)); router.post(resourcesPath(ACQUISITIONS_MEMBERSHIPS)).handler(ctx -> handlePostGenericSubObj(ctx, ACQUISITIONS_MEMBERSHIPS)); @@ -597,9 +606,11 @@ private Router defineRoutes() { router.post(resourcesPath(PREFIXES)).handler(ctx -> handlePostGenericSubObj(ctx, PREFIXES)); router.post(resourcesPath(SUFFIXES)).handler(ctx -> handlePostGenericSubObj(ctx, SUFFIXES)); router.post(resourcesPath(TAGS)).handler(ctx -> handlePostGenericSubObj(ctx, TAGS)); - + router.post(resourcesPath(DATA_EXPORT_SPRING_CREATE_JOB)).handler(ctx -> handlePostGenericSubObj(ctx, DATA_EXPORT_SPRING_CREATE_JOB)); + router.post(resourcesPath(DATA_EXPORT_SPRING_EXECUTE_JOB)).handler(ctx -> handlePostGenericSubObj(ctx, DATA_EXPORT_SPRING_EXECUTE_JOB)); + // GET router.get(resourcePath(PURCHASE_ORDER_STORAGE)).handler(this::handleGetPurchaseOrderById); - router.get(resourcesPath(PURCHASE_ORDER_STORAGE)).handler(ctx -> handleGetPurchaseOrderByQuery(ctx, PURCHASE_ORDER_STORAGE)); + router.get(resourcesPath(PURCHASE_ORDER_STORAGE)).handler(this::handleGetPurchaseOrderByQuery); router.get("/instance-types").handler(this::handleGetInstanceType); router.get("/instance-statuses").handler(this::handleGetInstanceStatus); router.get("/inventory/instances").handler(this::handleGetInstanceRecord); @@ -615,7 +626,7 @@ private Router defineRoutes() { router.get("/identifier-types").handler(this::handleGetIdentifierType); router.get("/holdings-sources").handler(this::handleGetHoldingsSource); router.get("/circulation/requests").handler(this::handleGetItemRequests); - router.get(resourcesPath(PO_LINES_STORAGE)).handler(ctx -> handleGetPoLines(ctx, PO_LINES_STORAGE)); + router.get(resourcesPath(PO_LINES_STORAGE)).handler(this::handleGetPoLines); router.get(resourcePath(PO_LINES_STORAGE)).handler(this::handleGetPoLineById); router.get(resourcePath(ALERTS)).handler(ctx -> handleGetGenericSubObj(ctx, ALERTS)); router.get(resourcePath(REPORTING_CODES)).handler(ctx -> handleGetGenericSubObj(ctx, REPORTING_CODES)); @@ -668,7 +679,7 @@ private Router defineRoutes() { router.get("/organizations/organizations").handler(this::handleGetOrganizations); router.get("/locations").handler(ctx -> handleGetJsonResource(ctx, MOCKDATA_LOCATIONS_JSON)); router.get("/material-types").handler(ctx -> handleGetJsonResource(ctx, MOCKDATA_MATERIAL_TYPES_JSON)); - + // PUT router.put(resourcePath(PURCHASE_ORDER_STORAGE)).handler(ctx -> handlePutGenericSubObj(ctx, PURCHASE_ORDER_STORAGE)); router.put(resourcePath(PO_LINES_STORAGE)).handler(ctx -> handlePutGenericSubObj(ctx, PO_LINES_STORAGE)); router.put(resourcesPath(PO_LINES_BATCH_STORAGE)).handler(ctx -> handlePutGenericSubObj(ctx, PO_LINES_BATCH_STORAGE)); @@ -686,8 +697,7 @@ private Router defineRoutes() { router.put(resourcePath(PREFIXES)).handler(ctx -> handlePutGenericSubObj(ctx, PREFIXES)); router.put(resourcePath(SUFFIXES)).handler(ctx -> handlePutGenericSubObj(ctx, SUFFIXES)); router.put(resourcePath(ACQUISITION_METHODS)).handler(ctx -> handlePutGenericSubObj(ctx, ACQUISITION_METHODS)); - - + // DELETE router.delete(resourcePath(PURCHASE_ORDER_STORAGE)).handler(ctx -> handleDeleteGenericSubObj(ctx, PURCHASE_ORDER_STORAGE)); router.delete(resourcePath(PO_LINES_STORAGE)).handler(ctx -> handleDeleteGenericSubObj(ctx, PO_LINES_STORAGE)); router.delete(resourcePath(ALERTS)).handler(ctx -> handleDeleteGenericSubObj(ctx, ALERTS)); @@ -703,21 +713,18 @@ private Router defineRoutes() { router.delete(resourcePath(PREFIXES)).handler(ctx -> handleDeleteGenericSubObj(ctx, PREFIXES)); router.delete(resourcePath(SUFFIXES)).handler(ctx -> handleDeleteGenericSubObj(ctx, SUFFIXES)); router.delete("/inventory/items/:id").handler(ctx -> handleDeleteGenericSubObj(ctx, ITEM_RECORDS)); - router.get("/configurations/entries").handler(this::handleConfigurationModuleResponse); - - router.patch(resourcePath(PO_LINES_STORAGE)).handler(ctx -> handlePatchOrderLines(ctx, PATCH_ORDER_LINES_REQUEST_PATCH)); + router.patch(resourcePath(PO_LINES_STORAGE)).handler(this::handlePatchOrderLines); return router; } private void handleGetExportHistoryMethod(RoutingContext ctx) { - logger.info("handleGetExportHistoryMethod got: " + ctx.request().path()); + logger.info("handleGetExportHistoryMethod got: {}", ctx.request().path()); try { JsonObject entries = new JsonObject(getMockData(EXPORT_HISTORY_PATH_TO_SAMPLES + "export_history_collection.json")); serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); addServerRqRsData(HttpMethod.GET, "exportHistory", entries); - } catch (IOException e) { ctx.response() .setStatusCode(404) @@ -726,21 +733,19 @@ private void handleGetExportHistoryMethod(RoutingContext ctx) { } private void handleGetFyRolloverProgress(RoutingContext ctx) { - logger.info("handleGetFyRolloverProgress got: " + ctx.request().path()); + logger.info("handleGetFyRolloverProgress got: {}", ctx.request().path()); try { JsonObject entries = new JsonObject(getMockData(LEDGER_FY_ROLLOVERS_PROGRESS_PATH + "ledger_fiscal_year_rollover_progress_collection.json")); serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); addServerRqRsData(HttpMethod.GET, "ledgerFiscalYearRolloverProgress", entries); - } catch (IOException e) { ctx.response() - .setStatusCode(404) - .end(); + .setStatusCode(404) + .end(); } } - private JsonObject getTitlesByPoLineIds(List poLineIds) { Supplier> getFromFile = () -> { try { @@ -758,7 +763,6 @@ private JsonObject getTitlesByPoLineIds(List poLineIds) { Object record = new TitleCollection().withTitles(titles).withTotalRecords(titles.size()); - return JsonObject.mapFrom(record); } @@ -788,7 +792,6 @@ private void handleGetFunds(RoutingContext ctx) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { try { - List ids = Collections.emptyList(); if (query.startsWith("id==")) { ids = extractIdsFromQuery(query); @@ -808,9 +811,9 @@ private void handleGetFunds(RoutingContext ctx) { } private void handleGetFundById(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetFundById got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); FundCollection funds = getFundsByIds(Collections.singletonList(id)) .mapTo(FundCollection.class); @@ -826,7 +829,6 @@ private void handleGetFundById(RoutingContext ctx) { serverResponse(ctx, 200, APPLICATION_JSON, fund.encodePrettily()); } - } private void handleGetBudgets(RoutingContext ctx) { @@ -836,7 +838,6 @@ private void handleGetBudgets(RoutingContext ctx) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { try { - List ids = Collections.emptyList(); if (query.startsWith("fundId==")) { ids = extractfundIdsFromQuery(query); @@ -855,7 +856,6 @@ private void handleGetBudgets(RoutingContext ctx) { } } - private void handleGetLedgers(RoutingContext ctx) { String query = StringUtils.trimToEmpty(ctx.request().getParam(QUERY)); addServerRqQuery(LEDGERS, query); @@ -863,7 +863,6 @@ private void handleGetLedgers(RoutingContext ctx) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { try { - List ids = Collections.emptyList(); if (query.startsWith("id==")) { ids = extractIdsFromQuery(query); @@ -899,7 +898,6 @@ private JsonObject getFundsByIds(List fundIds) { Object record = new FundCollection().withFunds(funds).withTotalRecords(funds.size()); - return JsonObject.mapFrom(record); } @@ -941,12 +939,11 @@ private JsonObject getLedgersByIds(List ledgerByFundIds) { Object record = new LedgerCollection().withLedgers(ledgers).withTotalRecords(ledgers.size()); - return JsonObject.mapFrom(record); } private void handleGetBudgetExpenseClass(RoutingContext ctx) { - logger.info("handleGetBudgetExpenseClass: " + ctx.request().path()); + logger.info("handleGetBudgetExpenseClass: {}", ctx.request().path()); try { BudgetExpenseClassCollection expenseClassCollection = new JsonObject(getMockData(BUDGET_EXPENSE_CLASSES_MOCK_DATA_PATH)) .mapTo(BudgetExpenseClassCollection.class); @@ -959,7 +956,7 @@ private void handleGetBudgetExpenseClass(RoutingContext ctx) { } private void handleGetExpenseClasses(RoutingContext ctx) { - logger.info("handleGetExpenseClasses: " + ctx.request().path()); + logger.info("handleGetExpenseClasses: {}", ctx.request().path()); try { ExpenseClassCollection expenseClassCollection = new JsonObject(getMockData(EXPENSE_CLASSES_MOCK_DATA_PATH)) .mapTo(ExpenseClassCollection.class); @@ -972,9 +969,9 @@ private void handleGetExpenseClasses(RoutingContext ctx) { } private void handleGetCurrentFiscalYearByLedgerId(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetCurrentFiscalYearByLedgerId got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); addServerRqRsData(HttpMethod.GET, PO_LINES_STORAGE, new JsonObject().put(ID, id)); @@ -1022,19 +1019,19 @@ private void handleGetPoLineNumber(RoutingContext ctx) { } private void handlePostInstanceRecord(RoutingContext ctx) { - logger.info("handlePostInstanceRecord got: " + ctx.body().asString()); + logger.info("handlePostInstanceRecord got: {}", ctx.body().asString()); JsonObject body = ctx.body().asJsonObject(); addServerRqRsData(HttpMethod.POST, INSTANCE_RECORD, body); ctx.response() .setStatusCode(201) .putHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) - .putHeader(HttpHeaders.LOCATION, ctx.request().absoluteURI() + "/" + UUID.randomUUID().toString()) + .putHeader(HttpHeaders.LOCATION, ctx.request().absoluteURI() + "/" + UUID.randomUUID()) .end(); } private void handlePostHoldingRecord(RoutingContext ctx) { - logger.info("handlePostHoldingsRecord got: " + ctx.body().asJsonObject()); + logger.info("handlePostHoldingsRecord got: {}", ctx.body().asJsonObject()); JsonObject body = ctx.body().asJsonObject(); // the case when item creation is expected to fail for particular holding @@ -1053,7 +1050,7 @@ private void handlePostHoldingRecord(RoutingContext ctx) { private void handlePostItemStorRecord(RoutingContext ctx) { String bodyAsString = ctx.body().toString(); - logger.info("handlePostItemRecord got: " + bodyAsString); + logger.info("handlePostItemRecord got: {}", bodyAsString); if (bodyAsString.contains(ID_FOR_INTERNAL_SERVER_ERROR)) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); @@ -1070,7 +1067,7 @@ private void handlePostItemStorRecord(RoutingContext ctx) { } private void handleGetInstanceRecord(RoutingContext ctx) { - logger.info("handleGetInstanceRecord got: " + ctx.request().path()); + logger.info("handleGetInstanceRecord got: {}", ctx.request().path()); try { JsonObject instance; @@ -1089,7 +1086,7 @@ private void handleGetInstanceRecord(RoutingContext ctx) { } private void handleGetInstanceRecordById(RoutingContext ctx) { - logger.info("handleGetInstanceRecordId got: " + ctx.request().path()); + logger.info("handleGetInstanceRecordId got: {}", ctx.request().path()); try { JsonObject instance = new JsonObject(getMockData(INSTANCE_RECORDS_MOCK_DATA_PATH + "instance.json")); @@ -1103,7 +1100,7 @@ private void handleGetInstanceRecordById(RoutingContext ctx) { } private void handleGetHoldingsRecords(RoutingContext ctx) { - logger.info("handleGetHoldingRecord got: " + ctx.request().path()); + logger.info("handleGetHoldingRecord got: {}", ctx.request().path()); String queryParam = ctx.queryParam("query").get(0); JsonObject holdings; try { @@ -1137,7 +1134,7 @@ private void handleGetHoldingsRecords(RoutingContext ctx) { List holdingsList = new JsonObject(getMockData(HOLDINGS_OLD_NEW_PATH)).getJsonArray("holdingsRecords") .stream() .map(JsonObject::mapFrom) - .collect(toList()); + .toList(); List doubleList = new ArrayList<>(holdingsList); doubleList.addAll(holdingsList); holdings = new JsonObject().put("holdingsRecords", new JsonArray(doubleList)); @@ -1179,7 +1176,7 @@ private JsonObject getHoldingsByIds(List holdingIds) { .toList(); } catch (IOException e) { holdingRecords = Collections.emptyList(); - }; + } } Object record = new JsonObject().put("holdingsRecords", new JsonArray(holdingRecords)); @@ -1188,9 +1185,9 @@ private JsonObject getHoldingsByIds(List holdingIds) { } private void handleGetHolding(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetHolding got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); JsonObject holding = new JsonObject(); holding.put("id", id); @@ -1202,27 +1199,24 @@ private void handleGetHolding(RoutingContext ctx) { } private void handleGetItemRecordsFromStorage(RoutingContext ctx) { - logger.info("handleGetItemRecordsFromStorage got: " + ctx.request().path()); + logger.info("handleGetItemRecordsFromStorage got: {}", ctx.request().path()); // Attempt to find POLine in mock server memory List itemsList = getRqRsEntries(HttpMethod.SEARCH, ITEM_RECORDS); + JsonObject items; if (!itemsList.isEmpty()) { - JsonObject items = new JsonObject() + items = new JsonObject() .put("items", itemsList) .put(TOTAL_RECORDS, itemsList.size()); - - addServerRqRsData(HttpMethod.GET, ITEM_RECORDS, items); - serverResponse(ctx, 200, APPLICATION_JSON, items.encodePrettily()); } else { - JsonObject items; items = new JsonObject().put("items", new JsonArray()); - addServerRqRsData(HttpMethod.GET, ITEM_RECORDS, items); - serverResponse(ctx, 200, APPLICATION_JSON, items.encodePrettily()); } + addServerRqRsData(HttpMethod.GET, ITEM_RECORDS, items); + serverResponse(ctx, 200, APPLICATION_JSON, items.encodePrettily()); } private void handleGetInventoryItemRecords(RoutingContext ctx) { - logger.info("handleGetInventoryItemRecords got: " + ctx.request().path()); + logger.info("handleGetInventoryItemRecords got: {}", ctx.request().path()); String query = ctx.request().getParam("query"); @@ -1265,7 +1259,7 @@ private void handleGetInventoryItemRecords(RoutingContext ctx) { JsonObject item = (JsonObject) iterator.next(); if (!purchaseOrderLineIdentifier.equals(item.getString(ITEM_PURCHASE_ORDER_LINE_IDENTIFIER)) - || !holdingsRecordId.equals(item.getString(ITEM_HOLDINGS_RECORD_ID))) { + || !holdingsRecordId.equals(item.getString(ITEM_HOLDINGS_RECORD_ID))) { iterator.remove(); } } @@ -1285,10 +1279,10 @@ private void handleGetInventoryItemRecords(RoutingContext ctx) { } private void handleGetInventoryItemRecordById(RoutingContext ctx) { - logger.info("handleGetInventoryItemRecordById got: " + ctx.request().path()); + logger.info("handleGetInventoryItemRecordById got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); if (id.equals(ID_FOR_INTERNAL_SERVER_ERROR)) { ctx.response().setStatusCode(500).end(); @@ -1307,7 +1301,7 @@ private void handleGetInventoryItemRecordById(RoutingContext ctx) { } } - if (jsonArray.size() > 0) { + if (!jsonArray.isEmpty()) { items.put(TOTAL_RECORDS, jsonArray.size()); addServerRqRsData(HttpMethod.GET, ITEM_RECORDS, jsonArray.getJsonObject(0)); @@ -1323,7 +1317,7 @@ private void handleGetInventoryItemRecordById(RoutingContext ctx) { } private void handleGetItemRequests(RoutingContext ctx) { - logger.info("handleGetItemRequests got: " + ctx.request().path()); + logger.info("handleGetItemRequests got: {}", ctx.request().path()); try { String itemId = ctx.request().getParam("query").split("and")[0].split("==")[1].trim(); if (itemId.startsWith("(") && itemId.endsWith(")")) { @@ -1346,7 +1340,7 @@ private void handleGetItemRequests(RoutingContext ctx) { } private void handleGetLoanType(RoutingContext ctx) { - logger.info("handleGetLoanType got: " + ctx.request().path()); + logger.info("handleGetLoanType got: {}", ctx.request().path()); String tenantId = ctx.request().getHeader(OKAPI_HEADER_TENANT); try { if (NON_EXIST_LOAN_TYPE_TENANT.equals(tenantId)) { @@ -1370,18 +1364,18 @@ private void handleGetLoanType(RoutingContext ctx) { } private void handleGetIdentifierType(RoutingContext ctx) { - logger.info("handleGetIdentifierType got: " + ctx.request().path()); + logger.info("handleGetIdentifierType got: {}", ctx.request().path()); try { - // Filter result based on name from query - String query = ctx.request().getParam("query"); - JsonObject entries = new JsonObject(getMockData(IDENTIFIER_TYPES_MOCK_DATA_PATH + "identifierTypes.json")); - if (query != null) { - String name = query.split("==")[1]; - filterByKeyValue("name", name, entries.getJsonArray(IDENTIFIER_TYPES)); - } + // Filter result based on name from query + String query = ctx.request().getParam("query"); + JsonObject entries = new JsonObject(getMockData(IDENTIFIER_TYPES_MOCK_DATA_PATH + "identifierTypes.json")); + if (query != null) { + String name = query.split("==")[1]; + filterByKeyValue("name", name, entries.getJsonArray(IDENTIFIER_TYPES)); + } - serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); - addServerRqRsData(HttpMethod.GET, IDENTIFIER_TYPES, entries); + serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); + addServerRqRsData(HttpMethod.GET, IDENTIFIER_TYPES, entries); } catch (IOException e) { ctx.response() .setStatusCode(404) @@ -1390,7 +1384,7 @@ private void handleGetIdentifierType(RoutingContext ctx) { } private void handleGetAccessProviders(RoutingContext ctx) { - logger.info("handleGetAccessProviders got: " + ctx.request().path()); + logger.info("handleGetAccessProviders got: {}", ctx.request().path()); String query = ctx.request().getParam("query"); JsonObject body = null; @@ -1413,10 +1407,8 @@ private void handleGetAccessProviders(RoutingContext ctx) { } else if (getQuery(ACTIVE_ACCESS_PROVIDER_B).equals(query)) { body = new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "one_access_providers_active.json")); } else if (getQuery(ORGANIZATION_NOT_VENDOR).equals(query)) { - body = new JsonObject( - getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "not_vendor.json")); - } - else { + body = new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "not_vendor.json")); + } else { JsonArray organizations = new JsonArray(); // Search for Organizations by id @@ -1444,8 +1436,9 @@ private void handleGetAccessProviders(RoutingContext ctx) { } private void getOrganizationById(RoutingContext ctx) { - logger.info("handleGetOrganizationById got: " + ctx.request().path()); + logger.info("handleGetOrganizationById got: {}", ctx.request().path()); String vendorId = ctx.request().getParam(ID); + logger.info("id: {}", vendorId); JsonObject body; if (NON_EXIST_VENDOR_ID.equals(vendorId)) { serverResponse(ctx, HttpStatus.HTTP_NOT_FOUND.toInt(), APPLICATION_JSON, "vendor not found"); @@ -1456,38 +1449,32 @@ private void getOrganizationById(RoutingContext ctx) { if (body != null) { serverResponse(ctx, HttpStatus.HTTP_OK.toInt(), APPLICATION_JSON, body.encodePrettily()); } else { + body = getMockEntry(ORGANIZATION_STORAGE, vendorId).orElse(null); + if (Objects.nonNull(body)) { + serverResponse(ctx, HttpStatus.HTTP_OK.toInt(), APPLICATION_JSON, body.encodePrettily()); + return; + } serverResponse(ctx, HttpStatus.HTTP_NOT_FOUND.toInt(), APPLICATION_JSON, "vendor not found"); } } } private JsonObject getOrganizationById(String organizationId) { - logger.debug("Searching for organization by id={}", organizationId); + logger.debug("Searching for organization by id: {}", organizationId); JsonObject body; try { - switch (organizationId) { - case ACTIVE_VENDOR_ID: - body = new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "active_vendor.json")); - break; - case INACTIVE_VENDOR_ID: - body = new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "inactive_vendor.json")); - break; - case PENDING_VENDOR_ID: - body = new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "pending_vendor.json")); - break; - case ACTIVE_ACCESS_PROVIDER_B: - body = new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "one_access_providers_active.json")) + body = switch (organizationId) { + case ACTIVE_VENDOR_ID -> new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "active_vendor.json")); + case INACTIVE_VENDOR_ID -> new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "inactive_vendor.json")); + case PENDING_VENDOR_ID -> new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "pending_vendor.json")); + case ACTIVE_ACCESS_PROVIDER_B -> + new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "one_access_providers_active.json")) .getJsonArray(ORGANIZATIONS).getJsonObject(0); - break; - case ORGANIZATION_NOT_VENDOR: - body = new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "not_vendor.json")); - break; - case VENDOR_WITH_BAD_CONTENT: - body = new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "vendor_bad_content.json")); - break; - default: - body = null; - } + case ORGANIZATION_NOT_VENDOR -> new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "not_vendor.json")); + case VENDOR_WITH_BAD_CONTENT -> + new JsonObject(getMockData(ORGANIZATIONS_MOCK_DATA_PATH + "vendor_bad_content.json")); + default -> null; + }; } catch (IOException e) { body = null; } @@ -1499,7 +1486,7 @@ private String getQuery(String... accessProviders) { } private void handleGetInstanceStatus(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetInstanceStatus got: {}", ctx.request().path()); String tenantId = ctx.request().getHeader(OKAPI_HEADER_TENANT); try { @@ -1522,7 +1509,7 @@ private void handleGetInstanceStatus(RoutingContext ctx) { } private void handleGetInstanceType(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetInstanceType got: {}", ctx.request().path()); String tenantId = ctx.request().getHeader(OKAPI_HEADER_TENANT); try { @@ -1549,7 +1536,7 @@ private void handleGetInstanceType(RoutingContext ctx) { } private void handleGetHoldingsSource(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetHoldingsSource got: {}", ctx.request().path()); String tenantId = ctx.request().getHeader(OKAPI_HEADER_TENANT); try { @@ -1589,7 +1576,7 @@ private void filterByKeyValue(String key, String value, JsonArray entries) { } private void handleGetReceivingHistory(RoutingContext ctx) { - logger.info("handleGetItemsRecords got: " + ctx.request().path()); + logger.info("handleGetItemsRecords got: {}", ctx.request().path()); String queryParam = StringUtils.trimToEmpty(ctx.request().getParam("query")); addServerRqQuery(RECEIVING_HISTORY, queryParam); try { @@ -1650,7 +1637,6 @@ private void handleConfigurationModuleResponse(RoutingContext ctx) { } catch (IOException e) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); } - } private void handleDeleteGenericSubObj(RoutingContext ctx, String subObj) { @@ -1671,11 +1657,11 @@ private void handleDeleteGenericSubObj(RoutingContext ctx, String subObj) { } } - private void handleGetPoLines(RoutingContext ctx, String type) { + private void handleGetPoLines(RoutingContext ctx) { logger.info("handleGetPoLines got: {}?{}", ctx.request().path(), ctx.request().query()); String queryParam = StringUtils.trimToEmpty(ctx.request().getParam("query")); - addServerRqQuery(type, queryParam); + addServerRqQuery(org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE, queryParam); if (queryParam.contains(BAD_QUERY)) { serverResponse(ctx, 400, APPLICATION_JSON, Response.Status.BAD_REQUEST.getReasonPhrase()); } else if (queryParam.contains(ID_FOR_INTERNAL_SERVER_ERROR) || queryParam.contains(PO_ID_GET_LINES_INTERNAL_SERVER_ERROR)) { @@ -1694,22 +1680,16 @@ private void handleGetPoLines(RoutingContext ctx, String type) { polIds = queryParam.startsWith("id==") ? extractIdsFromQuery(queryParam) : Collections.emptyList(); } - List postedPoLines = getRqRsEntries(HttpMethod.SEARCH, type); + List postedPoLines = getRqRsEntries(HttpMethod.SEARCH, org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE); try { PoLineCollection poLineCollection = new PoLineCollection(); if (postedPoLines.isEmpty()) { if (poId.equals(ORDER_ID_WITH_PO_LINES) || !polIds.isEmpty()) { - poLineCollection = new JsonObject(getMockData(POLINES_COLLECTION)).mapTo(PoLineCollection.class); + poLineCollection = new JsonObject(getMockData(PO_LINES_COLLECTION)).mapTo(PoLineCollection.class); // Filter PO Lines either by PO id or by expected line ids - Iterator iterator = poLineCollection.getPoLines().iterator(); - while (iterator.hasNext()) { - PoLine poLine = iterator.next(); - if (polIds.isEmpty() ? !poId.equals(poLine.getPurchaseOrderId()) : !polIds.contains(poLine.getId())) { - iterator.remove(); - } - } + poLineCollection.getPoLines().removeIf(poLine -> polIds.isEmpty() ? !poId.equals(poLine.getPurchaseOrderId()) : !polIds.contains(poLine.getId())); poLineCollection.setTotalRecords(poLineCollection.getPoLines().size()); } else { String filePath; @@ -1726,7 +1706,7 @@ private void handleGetPoLines(RoutingContext ctx, String type) { // Attempt to find POLine in mock server memory poLineCollection.getPoLines().addAll(postedPoLines.stream() .map(jsonObj -> jsonObj.mapTo(PoLine.class)) - .collect(Collectors.toList())); + .toList()); poLineCollection.getPoLines().removeIf(poLine -> !polIds.isEmpty() && !polIds.contains(poLine.getId())); } @@ -1738,30 +1718,27 @@ private void handleGetPoLines(RoutingContext ctx, String type) { JsonObject po_lines = JsonObject.mapFrom(poLineCollection); logger.info(po_lines.encodePrettily()); - addServerRqRsData(HttpMethod.GET, type, po_lines); + addServerRqRsData(HttpMethod.GET, org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE, po_lines); serverResponse(ctx, 200, APPLICATION_JSON, po_lines.encode()); } catch (NoSuchFileException e) { PoLineCollection poLineCollection = new PoLineCollection(); // Attempt to find POLine in mock server memory - if (postedPoLines != null) { - String finalPoId = poId; - poLineCollection.getPoLines().addAll(postedPoLines.stream() - .map(json -> json.mapTo(PoLine.class)) - .filter(line -> finalPoId.equals(line.getPurchaseOrderId())) - .collect(Collectors.toList())); - } + poLineCollection.getPoLines().addAll(postedPoLines.stream() + .map(json -> json.mapTo(PoLine.class)) + .filter(line -> poId.equals(line.getPurchaseOrderId())) + .toList()); poLineCollection.setTotalRecords(poLineCollection.getPoLines().size()); JsonObject entries = JsonObject.mapFrom(poLineCollection); - addServerRqRsData(HttpMethod.GET, type, entries); + addServerRqRsData(HttpMethod.GET, org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE, entries); serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); } catch (IOException e) { PoLineCollection poLineCollection = new PoLineCollection(); poLineCollection.setTotalRecords(0); JsonObject entries = JsonObject.mapFrom(poLineCollection); - addServerRqRsData(HttpMethod.GET, type, entries); + addServerRqRsData(HttpMethod.GET, org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE, entries); serverResponse(ctx, 200, APPLICATION_JSON, JsonObject.mapFrom(poLineCollection).encodePrettily()); } } @@ -1825,9 +1802,9 @@ private void replaceObjectsByIds(JsonObject line, String... property) { } private void handleGetPoLineById(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetPoLineById: got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); addServerRqRsData(HttpMethod.GET, PO_LINES_STORAGE, new JsonObject().put(ID, id)); @@ -1837,7 +1814,6 @@ private void handleGetPoLineById(RoutingContext ctx) { serverResponse(ctx, 200, APPLICATION_JSON, encodePrettily(getMinimalContentCompositePoLine())); } else { try { - // Attempt to find POLine in mock server memory JsonObject pol = getMockEntry(PO_LINES_STORAGE, id).orElse(null); @@ -1863,9 +1839,9 @@ private void serverResponse(RoutingContext ctx, int statusCode, String contentTy } private void handleGetGenericSubObj(RoutingContext ctx, String subObj) { - logger.info("got: " + ctx.request().path()); + logger.info("got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); JsonObject data = new JsonObject().put(ID, id); addServerRqRsData(HttpMethod.GET, subObj, data); @@ -1885,7 +1861,7 @@ private void handleGetGenericSubObj(RoutingContext ctx, String subObj) { } private void handleGetGenericSubObjs(RoutingContext ctx, String subObj) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetGenericSubObjs got: {}", ctx.request().path()); String query = StringUtils.trimToEmpty(ctx.request().getParam(QUERY)); addServerRqQuery(subObj, query); @@ -1923,8 +1899,9 @@ private void handleGetGenericSubObjs(RoutingContext ctx, String subObj) { } private void handleGetPieceById(RoutingContext ctx) { - logger.info("handleGetPiecesById got: " + ctx.request().path()); + logger.info("handleGetPiecesById got: {}", ctx.request().path()); String pieceId = ctx.request().getParam(ID); + logger.info("id: {}", pieceId); try { if (ID_DOES_NOT_EXIST.equals(pieceId)) { serverResponse(ctx, 404, APPLICATION_JSON, pieceId); @@ -1932,19 +1909,19 @@ private void handleGetPieceById(RoutingContext ctx) { serverResponse(ctx, 500, APPLICATION_JSON, pieceId); } else { // Attempt to find POLine in mock server memory - JsonObject body = getMockEntry(PIECES_STORAGE, pieceId).orElse(null); - if (body == null) { + JsonObject data = getMockEntry(PIECES_STORAGE, pieceId).orElse(null); + if (data == null) { if (PIECE_POLINE_CONSISTENCY_404_POLINE_NOT_FOUND_ID.equals(pieceId)) { - body = new JsonObject(getMockData(PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecord-poline-not-exists-5b454292-6aaa-474f-9510-b59a564e0c8d.json")); - + data = new JsonObject(getMockData(PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecord-poline-not-exists-5b454292-6aaa-474f-9510-b59a564e0c8d.json")); } else if (PIECE_POLINE_CONSISTENT_RECEIPT_STATUS_ID.equals(pieceId)) { - body = new JsonObject(getMockData(PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecord-received-consistent-receipt-status-5b454292-6aaa-474f-9510-b59a564e0c8d2.json")); + data = new JsonObject(getMockData(PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecord-received-consistent-receipt-status-5b454292-6aaa-474f-9510-b59a564e0c8d2.json")); } else { - body = new JsonObject(getMockData(PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecord-А.json")); + // Load piece by id + data = new JsonObject(getMockData(PIECE_RECORDS_MOCK_DATA_PATH + String.format("pieceRecord-%s.json", pieceId))); } } - serverResponse(ctx, HttpStatus.HTTP_OK.toInt(), APPLICATION_JSON, body.encodePrettily()); - + logger.info("handleGetPieceById, data: {}", data.encodePrettily()); + serverResponse(ctx, HttpStatus.HTTP_OK.toInt(), APPLICATION_JSON, data.encodePrettily()); } } catch (IOException e) { serverResponse(ctx, 404, APPLICATION_JSON, pieceId); @@ -1956,17 +1933,24 @@ private void handleGetPieces(RoutingContext ctx) { String requestQuery = ctx.request().getParam("query"); MultiMap requestHeaders = ctx.request().headers(); logger.info("handleGetPieces requestPath: {}, requestQuery: {}, requestHeaders: {}", requestPath, requestQuery, requestHeaders); - if (requestQuery.contains(ID_FOR_PIECES_INTERNAL_SERVER_ERROR)) { + if (Objects.nonNull(requestQuery) && requestQuery.contains(ID_FOR_PIECES_INTERNAL_SERVER_ERROR)) { logger.info("handleGetPieces (with internal server error)"); addServerRqRsData(HttpMethod.GET, PIECES_STORAGE, new JsonObject()); serverResponse(ctx, 500, APPLICATION_JSON, Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { PieceCollection pieces; + logger.info("handleGetPieces (all records), pieces already present: {}", getMockEntries(PIECES_STORAGE, Piece.class).isPresent()); + // Prevent loading of unnecessary pieces from other tests for tenant that was made specifically for Claiming if (getMockEntries(PIECES_STORAGE, Piece.class).isPresent()) { - logger.info("handleGetPieces (all records)"); + var isClaimingTenant = requestHeaders.contains(OKAPI_TENANT, EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10_CLAIMS.getValue(), false); + logger.info("handleGetPieces (all records), isClaimingTenant: {}", isClaimingTenant); try { List piecesList = getMockEntries(PIECES_STORAGE, Piece.class).get(); - pieces = new PieceCollection().withPieces(piecesList); + if (!isClaimingTenant) { + pieces = new PieceCollection().withPieces(piecesList); + } else { + pieces = new PieceCollection().withPieces(piecesList.stream().filter(piece -> piece.getReceivingStatus() == LATE).toList()); + } pieces.setTotalRecords(pieces.getPieces().size()); } catch (Exception e) { throw new IllegalStateException(String.format("Cannot retrieved mock data for requestPath: %s, requestQuery: %s", requestPath, requestQuery)); @@ -1989,20 +1973,19 @@ private void handleGetPieces(RoutingContext ctx) { status = condition.split("receivingStatus==")[1]; } } - logger.info("poLineId: " + polId); - logger.info("receivingStatus: " + status); + logger.info("poLineId: {}", polId); + logger.info("receivingStatus: {}", status); String path = PIECE_RECORDS_MOCK_DATA_PATH + String.format("pieceRecords-%s.json", polId); pieces = new JsonObject(getMockData(path)).mapTo(PieceCollection.class); // Filter piece records by receiving status if (StringUtils.isNotEmpty(status)) { Piece.ReceivingStatus receivingStatus = Piece.ReceivingStatus.fromValue(status); - pieces.getPieces() - .removeIf(piece -> receivingStatus != piece.getReceivingStatus()); + pieces.getPieces().removeIf(piece -> receivingStatus != piece.getReceivingStatus()); } } else if (requestQuery.contains("id==")) { logger.info("handleGetPieces (by id)"); - pieces = new JsonObject(getMockData(PIECE_RECORDS_MOCK_DATA_PATH + "pieceRecordsCollection.json")).mapTo(PieceCollection.class); + pieces = new JsonObject(getMockData(PIECES_COLLECTION)).mapTo(PieceCollection.class); List pieceIds = extractIdsFromQuery(requestQuery); pieces.getPieces().removeIf(piece -> !pieceIds.contains(piece.getId())); // fix consistency with titles: the piece's title id should be the same as one of the titles ids @@ -2020,7 +2003,6 @@ private void handleGetPieces(RoutingContext ctx) { } pieces.setTotalRecords(pieces.getPieces().size()); - } catch (Exception e) { logger.info("handleGetPieces (with empty piece collection on exception)"); pieces = new PieceCollection(); @@ -2030,6 +2012,7 @@ private void handleGetPieces(RoutingContext ctx) { JsonObject data = JsonObject.mapFrom(pieces); addServerRqRsData(HttpMethod.GET, PIECES_STORAGE, data); + logger.info("handleGetPieces, data: {}", data.encodePrettily()); ctx.response() .setStatusCode(200) @@ -2045,7 +2028,6 @@ private void handleGetTitles(RoutingContext ctx) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { try { - List ids = Collections.emptyList(); if (query.contains("poLineId==")) { ids = extractValuesFromQuery("poLineId", query); @@ -2065,9 +2047,9 @@ private void handleGetTitles(RoutingContext ctx) { } private void handleGetRoutingListById(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetRoutingListById got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); addServerRqRsData(HttpMethod.GET, ROUTING_LISTS, new JsonObject().put(ID, id)); @@ -2075,7 +2057,6 @@ private void handleGetRoutingListById(RoutingContext ctx) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { try { - // Attempt to find title in mock server memory JsonObject existantTitle = getMockEntry(ROUTING_LISTS, id).orElse(null); @@ -2099,7 +2080,6 @@ private void handleGetRoutingLists(RoutingContext ctx) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { try { - List ids = Collections.emptyList(); if (query.contains("poLineId==")) { ids = extractValuesFromQuery("poLineId", query); @@ -2138,7 +2118,7 @@ private List extractValuesFromQuery(String fieldName, String query) { } private void handlePutGenericSubObj(RoutingContext ctx, String subObj) { - logger.info("handlePutGenericSubObj got: PUT " + ctx.request().path()); + logger.info("handlePutGenericSubObj got: PUT {}", ctx.request().path()); String id = ctx.request().getParam(ID); addServerRqRsData(HttpMethod.PUT, subObj, ctx.body().asJsonObject()); @@ -2172,10 +2152,9 @@ private void addServerRqQuery(String objName, String query) { } private void handleGetPurchaseOrderById(RoutingContext ctx) { - logger.info("handleGetPurchaseOrderById got: GET " + ctx.request().path()); + logger.info("handleGetPurchaseOrderById got: GET {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); - + logger.info("id: {}", id); try { // Attempt to find PO in mock server memory JsonObject po = getMockEntry(PURCHASE_ORDER_STORAGE, id).orElse(null); @@ -2220,16 +2199,15 @@ private void handleGetPurchaseOrderById(RoutingContext ctx) { } } - private void handleGetPurchaseOrderByQuery(RoutingContext ctx, String orderType) { - + private void handleGetPurchaseOrderByQuery(RoutingContext ctx) { String query = StringUtils.substringAfter(ctx.request().absoluteURI(), "query="); - addServerRqQuery(orderType, query); + addServerRqQuery(org.folio.orders.utils.ResourcePathResolver.PURCHASE_ORDER_STORAGE, query); JsonObject po = new JsonObject(); PurchaseOrderCollection orderCollection = new PurchaseOrderCollection(); // Attempt to find POLine in mock server memory - List postedOrders = serverRqRs.column(HttpMethod.SEARCH).get(orderType); + List postedOrders = serverRqRs.column(HttpMethod.SEARCH).get(org.folio.orders.utils.ResourcePathResolver.PURCHASE_ORDER_STORAGE); if (postedOrders != null) { orderCollection @@ -2244,14 +2222,14 @@ private void handleGetPurchaseOrderByQuery(RoutingContext ctx, String orderType) po.remove("totalEstimatedPrice"); po.remove("totalItems"); - addServerRqRsData(HttpMethod.GET, orderType, po); + addServerRqRsData(HttpMethod.GET, org.folio.orders.utils.ResourcePathResolver.PURCHASE_ORDER_STORAGE, po); } else { if (query.contains(BAD_QUERY)) { serverResponse(ctx, 400, APPLICATION_JSON, Response.Status.BAD_REQUEST.getReasonPhrase()); } else if (query.contains(ID_FOR_INTERNAL_SERVER_ERROR)) { serverResponse(ctx, 500, APPLICATION_JSON, Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { - addServerRqRsData(HttpMethod.GET, orderType, po); + addServerRqRsData(HttpMethod.GET, org.folio.orders.utils.ResourcePathResolver.PURCHASE_ORDER_STORAGE, po); Matcher matcher = Pattern.compile(".*poNumber==(\\S[^)]+).*").matcher(query); final String poNumber = matcher.find() ? matcher.group(1) : EMPTY; switch (poNumber) { @@ -2267,7 +2245,7 @@ private void handleGetPurchaseOrderByQuery(RoutingContext ctx, String orderType) } private void handlePostPurchaseOrder(RoutingContext ctx) { - logger.info("got: " + ctx.body().asString()); + logger.info("handlePostPurchaseOrder got: {}", ctx.body().asString()); if (ORDER_ID_DUPLICATION_ERROR_USER_ID.equals(ctx.request().getHeader(RestVerticle.OKAPI_USERID_HEADER))) { JsonObject body = ctx.body().asJsonObject(); Error error = new Error() @@ -2290,23 +2268,8 @@ private void handlePostPurchaseOrder(RoutingContext ctx) { .end(JsonObject.mapFrom(po).encodePrettily()); } - private void handlePostGeneric(RoutingContext ctx, String objectType) { - logger.info("handlePostGeneric {} got: {}", objectType, ctx.body().asString()); - - if (objectType.equals(ctx.request().getHeader(HEADER_SERVER_ERROR))) { - serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); - } else { - String id = UUID.randomUUID().toString(); - JsonObject body = ctx.body().asJsonObject(); - body.put(ID, id); - addServerRqRsData(HttpMethod.POST, objectType, body); - - serverResponse(ctx, 201, APPLICATION_JSON, body.encodePrettily()); - } - } - private void handlePostGenericSubObj(RoutingContext ctx, String subObj) { - logger.info("got: " + ctx.body().asString()); + logger.info("handlePostGenericSubObj got: {}", ctx.body().asString()); String echoStatus = ctx.request().getHeader(X_ECHO_STATUS); @@ -2359,7 +2322,7 @@ private void handlePostGenericSubObj(RoutingContext ctx, String subObj) { } private void handleBatchTransactions(RoutingContext ctx) { - logger.info("handleBatchTransactions got: " + ctx.request().path()); + logger.info("handleBatchTransactions got: {}", ctx.request().path()); String tenant = ctx.request().getHeader(OKAPI_HEADER_TENANT); @@ -2425,7 +2388,6 @@ private void handleTransactionGetEntry(RoutingContext ctx) { .withSourcePoLineId("a6edc906-2f9f-5fb2-a373-efac406f0ef2") .withStatus(Encumbrance.Status.UNRELEASED)) .withMetadata(new Metadata()); - List transactions = List.of(transaction1); TransactionCollection transactionCollection = new TransactionCollection().withTransactions(List.of(transaction1, transaction2)).withTotalRecords(2); body = JsonObject.mapFrom(transactionCollection).encodePrettily(); } else if (query.contains("encumbrance.sourcePoLineId == 50fb5514-cdf1-11e8-a8d5-f2801f1b9fd1")) { @@ -2459,7 +2421,7 @@ private void handleTransactionGetEntry(RoutingContext ctx) { } private void handleUserTenantsGetEntry(RoutingContext ctx) { - String body = new JsonObject().put("userTenants", org.assertj.core.util.Lists.emptyList()).encodePrettily(); + String body = new JsonObject().put("userTenants", Collections.emptyList()).encodePrettily(); serverResponse(ctx, HttpStatus.HTTP_OK.toInt(), APPLICATION_JSON, body); addServerRqRsData(HttpMethod.GET, USER_TENANTS_ENDPOINT, new JsonObject(body)); } @@ -2478,6 +2440,7 @@ private Class getSubObjClass(String subObj) { case PREFIXES -> Prefix.class; case SUFFIXES -> Suffix.class; case TAGS -> Tag.class; + case DATA_EXPORT_SPRING_CREATE_JOB, DATA_EXPORT_SPRING_EXECUTE_JOB -> Object.class; default -> { fail("The sub-object is unknown"); yield null; @@ -2486,7 +2449,7 @@ private Class getSubObjClass(String subObj) { } private void handlePostPOLine(RoutingContext ctx) { - logger.info("got poLine: " + ctx.body().asString()); + logger.info("handlePostPOLine got poLine: {}", ctx.body().asString()); JsonObject body = ctx.body().asJsonObject(); org.folio.rest.acq.model.PoLine pol = body.mapTo(org.folio.rest.acq.model.PoLine.class); @@ -2494,7 +2457,6 @@ private void handlePostPOLine(RoutingContext ctx) { pol.setId(UUID.randomUUID().toString()); } - if (ID_FOR_INTERNAL_SERVER_ERROR.equals(pol.getPurchaseOrderId())) { ctx.response() .setStatusCode(500) @@ -2571,7 +2533,7 @@ private void handleGetContributorNameTypes(RoutingContext ctx) { }; private void handleGetAcquisitionsUnits(RoutingContext ctx) { - logger.info("handleGetAcquisitionsUnits got: " + ctx.request().path()); + logger.info("handleGetAcquisitionsUnits got: {}", ctx.request().path()); String tenant = ctx.request().getHeader(OKAPI_HEADER_TENANT); String query = StringUtils.trimToEmpty(ctx.request().getParam("query")); addServerRqQuery(ACQUISITIONS_UNITS, query); @@ -2588,7 +2550,7 @@ private void handleGetAcquisitionsUnits(RoutingContext ctx) { if (!query.contains(ALL_UNITS_CQL)) { List isDeleted = extractValuesFromQuery(IS_DELETED_PROP, query).stream() .map(Boolean::valueOf) - .collect(toList()); + .toList(); if (!isDeleted.isEmpty()) { units.getAcquisitionsUnits().removeIf(unit -> !isDeleted.contains(unit.getIsDeleted())); } @@ -2615,7 +2577,7 @@ private void handleGetAcquisitionsUnits(RoutingContext ctx) { } private void handleGetAcquisitionsUnit(RoutingContext ctx) { - logger.info("handleGetAcquisitionsUnits got: " + ctx.request().path()); + logger.info("handleGetAcquisitionsUnit got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); AcquisitionsUnitCollection units; @@ -2641,13 +2603,12 @@ private void handleGetAcquisitionsUnit(RoutingContext ctx) { } private void handleGetAcquisitionsMemberships(RoutingContext ctx) { - logger.info("handleGetAcquisitionsMemberships got: " + ctx.request().path()); + logger.info("handleGetAcquisitionsMemberships got: {}", ctx.request().path()); String query = StringUtils.trimToEmpty(ctx.request().getParam("query")); if (query.contains(BAD_QUERY)) { serverResponse(ctx, 400, APPLICATION_JSON, Response.Status.BAD_REQUEST.getReasonPhrase()); } else { - Matcher userIdMatcher = Pattern.compile(".*userId==(\\S+).*").matcher(query); final String userId = userIdMatcher.find() ? userIdMatcher.group(1) : EMPTY; @@ -2673,7 +2634,7 @@ private void handleGetAcquisitionsMemberships(RoutingContext ctx) { } private void handleGetAcquisitionsMembership(RoutingContext ctx) { - logger.info("handleGetAcquisitionsMembership got: " + ctx.request().path()); + logger.info("handleGetAcquisitionsMembership got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); AcquisitionsUnitMembershipCollection memberships; @@ -2699,7 +2660,7 @@ private void handleGetAcquisitionsMembership(RoutingContext ctx) { } private void handleGetAcquisitionMethod(RoutingContext ctx) { - logger.info("handleGetAcquisitionMethod got: " + ctx.request().path()); + logger.info("handleGetAcquisitionMethod got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); AcquisitionMethodCollection acquisitionMethodCollection; @@ -2725,13 +2686,12 @@ private void handleGetAcquisitionMethod(RoutingContext ctx) { } private void handleGetAcquisitionMethods(RoutingContext ctx) { - logger.info("handleGetAcquisitionMethods got: " + ctx.request().path()); + logger.info("handleGetAcquisitionMethods got: {}", ctx.request().path()); String query = StringUtils.trimToEmpty(ctx.request().getParam("query")); if (query.contains(BAD_QUERY)) { serverResponse(ctx, 400, APPLICATION_JSON, Response.Status.BAD_REQUEST.getReasonPhrase()); } else { - Matcher sourceMatcher = Pattern.compile(".*source==(\\S+).*").matcher(query); final String acquisitionMethodSource = sourceMatcher.find() ? sourceMatcher.group(1) : EMPTY; @@ -2757,8 +2717,7 @@ private void handleGetAcquisitionMethods(RoutingContext ctx) { } private void handleGetIsbnConverter(RoutingContext ctx) { - logger.info("handleGetIsbnConverter got: " + ctx.request() - .path()); + logger.info("handleGetIsbnConverter got: {}", ctx.request().path()); String isbn = ctx.request() .getParam("isbn"); JsonObject data = new JsonObject(); @@ -2776,7 +2735,7 @@ private void handleGetIsbnConverter(RoutingContext ctx) { } private void handleGetOrderTemplates(RoutingContext ctx) { - logger.info("handleGetOrderTemplates got: " + ctx.request().path()); + logger.info("handleGetOrderTemplates got: {}", ctx.request().path()); String query = StringUtils.trimToEmpty(ctx.request().getParam("query")); addServerRqQuery(ORDER_TEMPLATES, query); @@ -2784,7 +2743,6 @@ private void handleGetOrderTemplates(RoutingContext ctx) { if (query.contains(BAD_QUERY)) { serverResponse(ctx, 400, APPLICATION_JSON, Response.Status.BAD_REQUEST.getReasonPhrase()); } else { - Matcher templateCodeMatcher = Pattern.compile(".*templateCode==(\\S+).*").matcher(query); final String templateCode = templateCodeMatcher.find() ? templateCodeMatcher.group(1) : EMPTY; @@ -2810,11 +2768,10 @@ private void handleGetOrderTemplates(RoutingContext ctx) { } } - private void handleGetOrderTitleById(RoutingContext ctx) { - logger.info("got: " + ctx.request().path()); + logger.info("handleGetOrderTitleById got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); addServerRqRsData(HttpMethod.GET, TITLES, new JsonObject().put(ID, id)); @@ -2822,7 +2779,6 @@ private void handleGetOrderTitleById(RoutingContext ctx) { serverResponse(ctx, 500, APPLICATION_JSON, INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { try { - // Attempt to find title in mock server memory JsonObject existantTitle = getMockEntry(TITLES, id).orElse(null); @@ -2840,7 +2796,7 @@ private void handleGetOrderTitleById(RoutingContext ctx) { } private void handleGetBudgetByFinanceId(RoutingContext ctx) { - logger.info("handleGetInvoiceDocumentById got: GET " + ctx.request().path()); + logger.info("handleGetInvoiceDocumentById got: GET {}", ctx.request().path()); String fundId = ctx.request().getParam("id"); JsonObject collection = getBudgetsByFundIds(Collections.singletonList(fundId)); @@ -2862,7 +2818,7 @@ private void handleGetBudgetByFinanceId(RoutingContext ctx) { } private void handleGetRateOfExchange(RoutingContext ctx) { - logger.info("handleGetRateOfExchange: " + ctx.request().path()); + logger.info("handleGetRateOfExchange: {}", ctx.request().path()); String fromParam = StringUtils.trimToEmpty(ctx.request().getParam("from")); String toParam = StringUtils.trimToEmpty(ctx.request().getParam("to")); ExchangeRate exchangeRate = new ExchangeRate().withExchangeRate(1.0d).withFrom(fromParam).withTo(toParam); @@ -2870,14 +2826,13 @@ private void handleGetRateOfExchange(RoutingContext ctx) { serverResponse(ctx, 200, APPLICATION_JSON, JsonObject.mapFrom(exchangeRate).encodePrettily()); } - private void handleGetFyRollovers(RoutingContext ctx) { - logger.info("handleGetFyRollovers got: " + ctx.request().path()); + logger.info("handleGetFyRollovers got: {}", ctx.request().path()); try { - JsonObject entries = new JsonObject(getMockData(LEDGER_FY_ROLLOVERS_PATH + "ledger_fiscal_year_rollover_collection.json")); + JsonObject entries = new JsonObject(getMockData(LEDGER_FY_ROLLOVERS_PATH + "ledger_fiscal_year_rollover_collection.json")); - serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); - addServerRqRsData(HttpMethod.GET, "ledgerFiscalYearRollovers", entries); + serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); + addServerRqRsData(HttpMethod.GET, "ledgerFiscalYearRollovers", entries); } catch (IOException e) { String body = buildEmptyCollection("ledgerFiscalYearRollovers"); @@ -2887,13 +2842,12 @@ private void handleGetFyRollovers(RoutingContext ctx) { } private void handleGetFyRolloverErrors(RoutingContext ctx) { - logger.info("handleGetFyRolloverErrors got: " + ctx.request().path()); + logger.info("handleGetFyRolloverErrors got: {}", ctx.request().path()); try { - JsonObject entries = new JsonObject(getMockData(LEDGER_FY_ROLLOVERS_ERRORS_PATH + "ledger_fiscal_year_rollover_error_collection.json")); - - serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); - addServerRqRsData(HttpMethod.GET, "ledgerFiscalYearRolloverErrors", entries); + JsonObject entries = new JsonObject(getMockData(LEDGER_FY_ROLLOVERS_ERRORS_PATH + "ledger_fiscal_year_rollover_error_collection.json")); + serverResponse(ctx, 200, APPLICATION_JSON, entries.encodePrettily()); + addServerRqRsData(HttpMethod.GET, "ledgerFiscalYearRolloverErrors", entries); } catch (IOException e) { ctx.response() .setStatusCode(404) @@ -2902,12 +2856,11 @@ private void handleGetFyRolloverErrors(RoutingContext ctx) { } private void handleGetOrderInvoiceRelationship(RoutingContext ctx) { - logger.info("handleGetOrderInvoiceRelationship got: " + ctx.request().path()); + logger.info("handleGetOrderInvoiceRelationship got: {}", ctx.request().path()); JsonObject emptyCollection = JsonObject.mapFrom(new OrderInvoiceRelationshipCollection().withTotalRecords(0)); serverResponse(ctx, 200, APPLICATION_JSON, emptyCollection.encodePrettily()); addServerRqRsData(HttpMethod.GET, "orderInvoiceRelationship", emptyCollection); - } private void handleGetInvoiceLines(RoutingContext ctx) { @@ -2966,11 +2919,11 @@ private void handleGetInvoiceLines(RoutingContext ctx) { addServerRqRsData(HttpMethod.GET, "invoiceLines", jo); } - private void handlePatchOrderLines(RoutingContext ctx, String subObj) { - logger.info("handlePatchOrderLines got: PATCH " + ctx.request().path()); + private void handlePatchOrderLines(RoutingContext ctx) { + logger.info("handlePatchOrderLines got: PATCH {}", ctx.request().path()); String id = ctx.request().getParam(ID); - addServerRqRsData(HttpMethod.PATCH, subObj, ctx.body().asJsonObject()); + addServerRqRsData(HttpMethod.PATCH, MockServer.PATCH_ORDER_LINES_REQUEST_PATCH, ctx.body().asJsonObject()); if (ID_DOES_NOT_EXIST.equals(id)) { serverResponse(ctx, 404, APPLICATION_JSON, id); @@ -2987,9 +2940,9 @@ private void handlePatchOrderLines(RoutingContext ctx, String subObj) { } private void handleGetJobProfileSnapshotById(RoutingContext ctx) { - logger.info("handleGetJobProfileSnapshotById got: " + ctx.request().path()); + logger.info("handleGetJobProfileSnapshotById got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); if (ID_FOR_INTERNAL_SERVER_ERROR.equals(id)) { serverResponse(ctx, 500, APPLICATION_JSON, Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { @@ -3007,9 +2960,9 @@ private void handleGetJobProfileSnapshotById(RoutingContext ctx) { } private void handleGetJobExecutionById(RoutingContext ctx) { - logger.info("handleGetJobExecutionById got: " + ctx.request().path()); + logger.info("handleGetJobExecutionById got: {}", ctx.request().path()); String id = ctx.request().getParam(ID); - logger.info("id: " + id); + logger.info("id: {}", id); if (ID_FOR_INTERNAL_SERVER_ERROR.equals(id)) { serverResponse(ctx, 500, APPLICATION_JSON, Response.Status.INTERNAL_SERVER_ERROR.getReasonPhrase()); } else { @@ -3023,7 +2976,7 @@ private void handleGetJobExecutionById(RoutingContext ctx) { } private void handleGetOrganizations(RoutingContext ctx) { - logger.info("handleGetOrganizations:: got: " + ctx.request().path()); + logger.info("handleGetOrganizations:: got: {}", ctx.request().path()); Optional> organizationsOptional = getMockEntries("organizations", Organization.class); if (organizationsOptional.isPresent()) { List organizations = organizationsOptional.get(); diff --git a/src/test/java/org/folio/rest/impl/PieceApiTest.java b/src/test/java/org/folio/rest/impl/PieceApiTest.java index f1fcb903c..e4294800e 100644 --- a/src/test/java/org/folio/rest/impl/PieceApiTest.java +++ b/src/test/java/org/folio/rest/impl/PieceApiTest.java @@ -38,7 +38,7 @@ import static org.folio.rest.impl.MockServer.ECS_UNIVERSITY_HOLDINGS_RECORD_JSON; import static org.folio.rest.impl.MockServer.ECS_UNIVERSITY_INSTANCE_JSON; import static org.folio.rest.impl.MockServer.ECS_UNIVERSITY_ITEM_JSON; -import static org.folio.rest.impl.MockServer.POLINES_COLLECTION; +import static org.folio.rest.impl.MockServer.PO_LINES_COLLECTION; import static org.folio.rest.impl.MockServer.addMockEntry; import static org.folio.rest.impl.MockServer.getCreatedItems; import static org.folio.rest.impl.MockServer.getCreatedPieces; @@ -157,7 +157,7 @@ void testPostPiece() { void testPostPhysicalPieceCancelledPurchaseOrder() { logger.info("=== Test POST physical piece with a cancelled purchase order ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(14).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(14).mapTo(CompositePoLine.class); CompositePurchaseOrder compositePurchaseOrder = new CompositePurchaseOrder().withId(compositePoLine.getPurchaseOrderId()).withWorkflowStatus(CompositePurchaseOrder.WorkflowStatus.CLOSED); Title tile = getTitle(compositePoLine); addMockEntry(PURCHASE_ORDER_STORAGE, compositePurchaseOrder); @@ -208,7 +208,7 @@ private static Stream testPostPieceCancelledOrderLineArgs() { void testPostPieceCancelledOrderLine(int poLineIdx, CheckInPiece.ItemStatus itemStatus) { logger.info("=== Test POST physical piece with a cancelled order line ==="); - CompositePoLine compositePoLine = getMockAsJson(POLINES_COLLECTION).getJsonArray("poLines").getJsonObject(poLineIdx).mapTo(CompositePoLine.class); + CompositePoLine compositePoLine = getMockAsJson(PO_LINES_COLLECTION).getJsonArray("poLines").getJsonObject(poLineIdx).mapTo(CompositePoLine.class); CompositePurchaseOrder compositePurchaseOrder = new CompositePurchaseOrder().withId(compositePoLine.getPurchaseOrderId()).withWorkflowStatus(CompositePurchaseOrder.WorkflowStatus.OPEN); Title tile = getTitle(compositePoLine); addMockEntry(PURCHASE_ORDER_STORAGE, compositePurchaseOrder); diff --git a/src/test/java/org/folio/rest/impl/PiecesClaimingApiTest.java b/src/test/java/org/folio/rest/impl/PiecesClaimingApiTest.java new file mode 100644 index 000000000..c72ef5d9b --- /dev/null +++ b/src/test/java/org/folio/rest/impl/PiecesClaimingApiTest.java @@ -0,0 +1,227 @@ +package org.folio.rest.impl; + +import io.restassured.http.Header; +import io.vertx.core.json.JsonObject; +import io.vertx.junit5.VertxExtension; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.folio.ApiTestSuite; +import org.folio.Organization; +import org.folio.config.ApplicationConfig; +import org.folio.rest.jaxrs.model.ClaimingCollection; +import org.folio.rest.jaxrs.model.ClaimingPieceResult; +import org.folio.rest.jaxrs.model.ClaimingResults; +import org.folio.rest.jaxrs.model.CompositePoLine; +import org.folio.rest.jaxrs.model.Piece; +import org.folio.rest.jaxrs.model.PieceCollection; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Collection; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; + +import static io.netty.handler.codec.http.HttpResponseStatus.CREATED; +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.clearServiceInteractions; +import static org.folio.TestConfig.initSpringContext; +import static org.folio.TestConfig.isVerticleNotDeployed; +import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10; +import static org.folio.TestConstants.EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10_CLAIMS; +import static org.folio.TestConstants.PIECES_CLAIMING_ENDPOINT; +import static org.folio.TestUtils.getMinimalOrder; +import static org.folio.TestUtils.getMockAsJson; +import static org.folio.models.claiming.IntegrationDetailField.CLAIM_PIECE_IDS; +import static org.folio.models.claiming.IntegrationDetailField.EXPORT_TYPE_SPECIFIC_PARAMETERS; +import static org.folio.models.claiming.IntegrationDetailField.VENDOR_EDI_ORDERS_EXPORT_CONFIG; +import static org.folio.orders.utils.ResourcePathResolver.ORGANIZATION_STORAGE; +import static org.folio.orders.utils.ResourcePathResolver.PIECES_STORAGE; +import static org.folio.orders.utils.ResourcePathResolver.PO_LINES_STORAGE; +import static org.folio.orders.utils.ResourcePathResolver.PURCHASE_ORDER_STORAGE; +import static org.folio.rest.impl.MockServer.BASE_MOCK_DATA_PATH; +import static org.folio.rest.impl.MockServer.ORGANIZATION_COLLECTION; +import static org.folio.rest.impl.MockServer.PIECES_COLLECTION; +import static org.folio.rest.impl.MockServer.PO_LINES_COLLECTION; +import static org.folio.rest.impl.MockServer.addMockEntry; +import static org.folio.rest.impl.MockServer.getDataExportSpringJobCreations; +import static org.folio.rest.impl.MockServer.getDataExportSpringJobExecutions; +import static org.folio.rest.impl.MockServer.getOrganizationSearches; +import static org.folio.rest.impl.MockServer.getPieceSearches; +import static org.folio.rest.impl.MockServer.getPieceUpdates; +import static org.folio.rest.impl.MockServer.getPoLineSearches; +import static org.folio.rest.impl.MockServer.getPurchaseOrderRetrievals; +import static org.folio.rest.jaxrs.model.ClaimingPieceResult.Status.FAILURE; +import static org.folio.rest.jaxrs.model.ClaimingPieceResult.Status.SUCCESS; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; + +@ExtendWith(VertxExtension.class) +public class PiecesClaimingApiTest { + + private static final Logger logger = LogManager.getLogger(); + private static boolean runningOnOwn; + + private static final String ORGANIZATIONS_KEY = "organizations"; + private static final String PO_LINES_KEY = "poLines"; + private static final String PIECES_KEY = "pieces"; + private static final String ENTRY_ID = "id"; + private static final String CLAIMING_MOCK_DATA_FOLDER = "claiming/"; + + @BeforeAll + static void before() throws InterruptedException, ExecutionException, TimeoutException { + if (isVerticleNotDeployed()) { + ApiTestSuite.before(); + runningOnOwn = true; + } + initSpringContext(ApplicationConfig.class); + } + + @AfterEach + void afterEach() throws Exception { + clearServiceInteractions(); + } + + @AfterAll + static void after() { + if (runningOnOwn) { + ApiTestSuite.after(); + } + } + + private static Stream testPostPiecesClaimArgs() { + var payloadFile = "send-claims-1-piece-1-vendor-1-job.json"; + var mockHitDto = new MockHitDto(3, 2, 2, 1, 1, 1, 1, 1); + return Stream.of( + Arguments.of("One piece One vendor One Job", 0, 17, 69, mockHitDto, payloadFile, EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10_CLAIMS, SUCCESS), + Arguments.of("One piece One vendor No Job", 0, 17, 69, null, payloadFile, EXIST_CONFIG_X_OKAPI_TENANT_LIMIT_10, FAILURE) + ); + } + + static class MockHitDto { + + private final int pieceSearches; + private final int polSearches; + private final int purchaseOrderRetrievals; + private final int organizationSearches; + private final int pieceUpdates; + private final int claimingResults; + private final int jobCreations; + private final int jobExecutions; + + public MockHitDto(int pieceSearches, int polSearches, int purchaseOrderRetrievals, + int organizationSearches, int pieceUpdates, int claimingResults, + int jobCreations, int jobExecutions) { + this.pieceSearches = pieceSearches; + this.polSearches = polSearches; + this.purchaseOrderRetrievals = purchaseOrderRetrievals; + this.organizationSearches = organizationSearches; + this.pieceUpdates = pieceUpdates; + this.claimingResults = claimingResults; + this.jobCreations = jobCreations; + this.jobExecutions = jobExecutions; + } + } + + @ParameterizedTest + @MethodSource("testPostPiecesClaimArgs") + void testPostPiecesClaim(String name, int vendorIdx, int poLineIdx, int pieceIdx, MockHitDto dto, + String payloadFile, Header header, ClaimingPieceResult.Status expectedStatus) { + logger.info("Testing postPiecesClaim, name: {}", name); + + var organization = getMockAsJson(ORGANIZATION_COLLECTION) + .getJsonArray(ORGANIZATIONS_KEY).getJsonObject(vendorIdx) + .mapTo(Organization.class); + var poLine = getMockAsJson(PO_LINES_COLLECTION) + .getJsonArray(PO_LINES_KEY) + .getJsonObject(poLineIdx) + .mapTo(CompositePoLine.class); + var purchaseOrder = getMinimalOrder(poLine) + .withVendor(organization.getId()); + var piece = getMockAsJson(PIECES_COLLECTION) + .getJsonArray(PIECES_KEY) + .getJsonObject(pieceIdx) + .mapTo(Piece.class); + + addMockEntry(ORGANIZATION_STORAGE, organization); + addMockEntry(PURCHASE_ORDER_STORAGE, purchaseOrder); + addMockEntry(PO_LINES_STORAGE, poLine); + addMockEntry(PIECES_STORAGE, piece); + + var mockDataPath = BASE_MOCK_DATA_PATH + CLAIMING_MOCK_DATA_FOLDER + payloadFile; + var request = getMockAsJson(mockDataPath).mapTo(ClaimingCollection.class); + var response = verifyPostResponse(PIECES_CLAIMING_ENDPOINT, JsonObject.mapFrom(request).encode(), prepareHeaders(header), APPLICATION_JSON, CREATED.code()) + .as(ClaimingResults.class); + + // Filter out any dummy pieces without ids that are loaded from other tests + var pieceSearches = getPieceSearches().stream() + .map(JsonObject::mapFrom).map(json -> json.mapTo(PieceCollection.class)) + .map(collection -> collection.getPieces().stream() + .filter(entry -> Objects.nonNull(entry.getId())).filter(entry -> entry.getId().equals(piece.getId())) + .toList()) + .flatMap(Collection::stream) + .toList(); + var polSearches = getPoLineSearches().stream() + .map(JsonObject::mapFrom).map(json -> json.getString(ENTRY_ID)) + .filter(Objects::nonNull).filter(poLineId -> poLineId.equals(poLine.getId())) + .toList(); + var purchaseOrderRetrievals = getPurchaseOrderRetrievals().stream() + .map(JsonObject::mapFrom).map(json -> json.getString(ENTRY_ID)) + .filter(Objects::nonNull).filter(poLineId -> poLineId.equals(purchaseOrder.getId())) + .toList(); + purchaseOrderRetrievals.forEach(entry -> logger.info("PurchaseOrders: {}", entry)); + var organizationSearches = getOrganizationSearches(); + var pieceUpdates = getPieceUpdates(); + var jobCreations = getDataExportSpringJobCreations(); + var jobExecutions = getDataExportSpringJobExecutions(); + + if (Objects.nonNull(dto)) { + assertThat(pieceSearches, not(nullValue())); + assertThat(polSearches, not(nullValue())); + assertThat(purchaseOrderRetrievals, not(nullValue())); + assertThat(organizationSearches, not(nullValue())); + assertThat(pieceUpdates, not(nullValue())); + assertThat(jobCreations, not(nullValue())); + assertThat(jobExecutions, not(nullValue())); + assertThat(pieceSearches, hasSize(dto.pieceSearches)); + assertThat(polSearches, hasSize(dto.polSearches)); + assertThat(purchaseOrderRetrievals, hasSize(dto.purchaseOrderRetrievals)); + assertThat(organizationSearches, hasSize(dto.organizationSearches)); + assertThat(pieceUpdates, hasSize(dto.pieceUpdates)); + assertThat(jobCreations, hasSize(dto.jobCreations)); + assertThat(jobExecutions, hasSize(dto.jobExecutions)); + assertThat(response.getClaimingPieceResults().size(), equalTo(dto.claimingResults)); + var claimedPieceIds = jobCreations.stream() + .peek(job -> logger.info("Created job: {}", JsonObject.mapFrom(job).encodePrettily())) + .map(job -> job.getJsonObject(EXPORT_TYPE_SPECIFIC_PARAMETERS.getValue()) + .getJsonObject(VENDOR_EDI_ORDERS_EXPORT_CONFIG.getValue()) + .getJsonArray(CLAIM_PIECE_IDS.getValue()).size()) + .mapToInt(value -> value).sum(); + assertThat(claimedPieceIds, equalTo(request.getClaimingPieceIds().size())); + } + + response.getClaimingPieceResults() + .forEach(result -> { + assertThat(result.getPieceId(), not(nullValue())); + assertThat(result.getStatus(), is(expectedStatus)); + if (expectedStatus == SUCCESS) { + assertThat(result.getError(), is(nullValue())); + } else { + assertThat(result.getError(), is(notNullValue())); + } + }); + } +} diff --git a/src/test/java/org/folio/service/pieces/PiecesClaimingServiceTest.java b/src/test/java/org/folio/service/pieces/PiecesClaimingServiceTest.java new file mode 100644 index 000000000..d74651a3c --- /dev/null +++ b/src/test/java/org/folio/service/pieces/PiecesClaimingServiceTest.java @@ -0,0 +1,295 @@ +package org.folio.service.pieces; + +import io.vertx.core.Future; +import io.vertx.core.json.JsonObject; +import io.vertx.junit5.VertxExtension; +import io.vertx.junit5.VertxTestContext; +import org.folio.CopilotGenerated; +import org.folio.rest.acq.model.Organization; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.jaxrs.model.ClaimingCollection; +import org.folio.rest.jaxrs.model.ClaimingPieceResult; +import org.folio.rest.jaxrs.model.Piece; +import org.folio.rest.jaxrs.model.PoLine; +import org.folio.rest.jaxrs.model.PurchaseOrder; +import org.folio.service.caches.ConfigurationEntriesCache; +import org.folio.service.orders.PurchaseOrderLineService; +import org.folio.service.orders.PurchaseOrderStorageService; +import org.folio.service.organization.OrganizationService; +import org.folio.service.pieces.flows.update.PieceUpdateFlowManager; +import org.folio.rest.core.RestClient; +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; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import static org.folio.models.claiming.ClaimingError.CANNOT_FIND_PIECES_WITH_LATE_STATUS_TO_PROCESS; +import static org.folio.models.claiming.ClaimingError.CANNOT_RETRIEVE_CONFIG_ENTRIES; +import static org.folio.models.claiming.ClaimingError.CANNOT_SEND_CLAIMS_PIECE_IDS_ARE_EMPTY; +import static org.folio.models.claiming.IntegrationDetailField.CLAIM_PIECE_IDS; +import static org.folio.models.claiming.IntegrationDetailField.EXPORT_TYPE_SPECIFIC_PARAMETERS; +import static org.folio.models.claiming.IntegrationDetailField.VENDOR_EDI_ORDERS_EXPORT_CONFIG; +import static org.folio.orders.utils.ResourcePathResolver.DATA_EXPORT_SPRING_CREATE_JOB; +import static org.folio.orders.utils.ResourcePathResolver.resourcesPath; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(VertxExtension.class) +@CopilotGenerated(partiallyGenerated = true) +public class PiecesClaimingServiceTest { + + @Mock private ConfigurationEntriesCache configurationEntriesCache; + @Mock private PieceStorageService pieceStorageService; + @Mock private PurchaseOrderLineService purchaseOrderLineService; + @Mock private PurchaseOrderStorageService purchaseOrderStorageService; + @Mock private OrganizationService organizationService; + @Mock private PieceUpdateFlowManager pieceUpdateFlowManager; + @Mock private RestClient restClient; + @InjectMocks private PiecesClaimingService piecesClaimingService; + + private AutoCloseable openedMocks; + + @BeforeEach + void setUp() { + openedMocks = MockitoAnnotations.openMocks(this); + } + + @AfterEach + void tearDown() throws Exception { + openedMocks.close(); + } + + @Test + void testSendClaims_emptyClaimingPieceIds(VertxTestContext testContext) { + var claimingCollection = new ClaimingCollection().withClaimingPieceIds(List.of()); + var requestContext = mock(RequestContext.class); + + piecesClaimingService.sendClaims(claimingCollection, requestContext) + .onComplete(testContext.succeeding(result -> testContext.verify(() -> { + assertEquals(1, result.getClaimingPieceResults().size()); + assertEquals(CANNOT_SEND_CLAIMS_PIECE_IDS_ARE_EMPTY.getValue(), result.getClaimingPieceResults().get(0).getError().getMessage()); + testContext.completeNow(); + }))); + } + + @Test + void testSendClaims_noConfigEntries(VertxTestContext testContext) { + var claimingCollection = new ClaimingCollection().withClaimingPieceIds(List.of("pieceId1")); + var requestContext = mock(RequestContext.class); + + when(configurationEntriesCache.loadConfiguration(any(), any())).thenReturn(Future.succeededFuture(new JsonObject())); + + piecesClaimingService.sendClaims(claimingCollection, requestContext) + .onComplete(testContext.succeeding(result -> testContext.verify(() -> { + assertEquals(1, result.getClaimingPieceResults().size()); + assertEquals(CANNOT_RETRIEVE_CONFIG_ENTRIES.getValue(), result.getClaimingPieceResults().get(0).getError().getMessage()); + testContext.completeNow(); + }))); + } + + @Test + void testSendClaims_noPiecesFound(VertxTestContext testContext) { + var claimingCollection = new ClaimingCollection().withClaimingPieceIds(List.of("pieceId1")); + var requestContext = mock(RequestContext.class); + + when(configurationEntriesCache.loadConfiguration(any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("key", "value"))); + when(pieceStorageService.getPiecesByIds(any(), any())).thenReturn(Future.succeededFuture(List.of())); + + piecesClaimingService.sendClaims(claimingCollection, requestContext) + .onComplete(testContext.succeeding(result -> testContext.verify(() -> { + assertEquals(1, result.getClaimingPieceResults().size()); + assertEquals(CANNOT_FIND_PIECES_WITH_LATE_STATUS_TO_PROCESS.getValue(), result.getClaimingPieceResults().get(0).getError().getMessage()); + testContext.completeNow(); + }))); + } + + @Test + void testSendClaims_pieceStatusNotLate(VertxTestContext testContext) { + var claimingCollection = new ClaimingCollection().withClaimingPieceIds(List.of("pieceId1")); + var requestContext = mock(RequestContext.class); + + when(configurationEntriesCache.loadConfiguration(any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("CLAIMS_vendorId", createIntegrationDetail()))); + when(pieceStorageService.getPiecesByIds(any(), any())).thenReturn(Future.succeededFuture(List.of(new Piece().withId("pieceId1").withPoLineId("poLineId1").withReceivingStatus(Piece.ReceivingStatus.RECEIVED)))); + when(purchaseOrderLineService.getOrderLineById(any(), any())).thenReturn(Future.succeededFuture(new PoLine().withPurchaseOrderId("orderId1"))); + when(purchaseOrderStorageService.getPurchaseOrderById(any(), any())).thenReturn(Future.succeededFuture(new PurchaseOrder().withVendor("vendorId"))); + when(organizationService.getVendorById(any(), any())).thenReturn(Future.succeededFuture(new Organization().withId("vendorId").withIsVendor(true))); + when(pieceUpdateFlowManager.updatePiecesStatuses(any(), any(), any())).thenReturn(Future.succeededFuture()); + when(restClient.post(eq(resourcesPath(DATA_EXPORT_SPRING_CREATE_JOB)), any(), any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("status", "CREATED"))); + when(restClient.postEmptyResponse(any(), any(), any())).thenReturn(Future.succeededFuture()); + + piecesClaimingService.sendClaims(claimingCollection, requestContext) + .onComplete(testContext.succeeding(result -> testContext.verify(() -> { + assertEquals(1, result.getClaimingPieceResults().size()); + assertEquals(CANNOT_FIND_PIECES_WITH_LATE_STATUS_TO_PROCESS.getValue(), result.getClaimingPieceResults().get(0).getError().getMessage()); + testContext.completeNow(); + }))); + } + + @Test + void testSendClaims_success(VertxTestContext testContext) { + var claimingCollection = new ClaimingCollection().withClaimingPieceIds(List.of("pieceId1")); + var requestContext = mock(RequestContext.class); + + when(configurationEntriesCache.loadConfiguration(any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("CLAIMS_vendorId", createIntegrationDetail()))); + when(pieceStorageService.getPiecesByIds(any(), any())).thenReturn(Future.succeededFuture(List.of(new Piece().withId("pieceId1").withPoLineId("poLineId1").withReceivingStatus(Piece.ReceivingStatus.LATE)))); + when(purchaseOrderLineService.getOrderLineById(any(), any())).thenReturn(Future.succeededFuture(new PoLine().withPurchaseOrderId("orderId1"))); + when(purchaseOrderStorageService.getPurchaseOrderById(any(), any())).thenReturn(Future.succeededFuture(new PurchaseOrder().withVendor("vendorId"))); + when(organizationService.getVendorById(any(), any())).thenReturn(Future.succeededFuture(new Organization().withId("vendorId").withIsVendor(true))); + when(pieceUpdateFlowManager.updatePiecesStatuses(any(), any(), any())).thenReturn(Future.succeededFuture()); + when(restClient.post(eq(resourcesPath(DATA_EXPORT_SPRING_CREATE_JOB)), any(), any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("status", "CREATED"))); + when(restClient.postEmptyResponse(any(), any(), any())).thenReturn(Future.succeededFuture()); + + piecesClaimingService.sendClaims(claimingCollection, requestContext) + .onComplete(testContext.succeeding(result -> testContext.verify(() -> { + assertEquals(1, result.getClaimingPieceResults().size()); + assertEquals("pieceId1", result.getClaimingPieceResults().get(0).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, result.getClaimingPieceResults().get(0).getStatus()); + testContext.completeNow(); + }))); + } + + @Test + void testSendClaims_successWithTwoPieces(VertxTestContext testContext) { + var claimingCollection = new ClaimingCollection().withClaimingPieceIds(List.of("pieceId1", "pieceId2")); + var requestContext = mock(RequestContext.class); + + when(configurationEntriesCache.loadConfiguration(any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("CLAIMS_vendorId", createIntegrationDetail()))); + when(pieceStorageService.getPiecesByIds(any(), any())).thenReturn(Future.succeededFuture(List.of( + new Piece().withId("pieceId1").withPoLineId("poLineId1").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId2").withPoLineId("poLineId2").withReceivingStatus(Piece.ReceivingStatus.LATE) + ))); + when(purchaseOrderLineService.getOrderLineById(any(), any())).thenReturn(Future.succeededFuture(new PoLine().withPurchaseOrderId("orderId1"))); + when(purchaseOrderStorageService.getPurchaseOrderById(any(), any())).thenReturn(Future.succeededFuture(new PurchaseOrder().withVendor("vendorId"))); + when(organizationService.getVendorById(any(), any())).thenReturn(Future.succeededFuture(new Organization().withId("vendorId").withIsVendor(true))); + when(pieceUpdateFlowManager.updatePiecesStatuses(any(), any(), any())).thenReturn(Future.succeededFuture()); + when(restClient.post(eq(resourcesPath(DATA_EXPORT_SPRING_CREATE_JOB)), any(), any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("status", "CREATED"))); + when(restClient.postEmptyResponse(any(), any(), any())).thenReturn(Future.succeededFuture()); + + piecesClaimingService.sendClaims(claimingCollection, requestContext) + .onComplete(testContext.succeeding(result -> testContext.verify(() -> { + assertEquals(2, result.getClaimingPieceResults().size()); + assertEquals("pieceId1", result.getClaimingPieceResults().get(0).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, result.getClaimingPieceResults().get(0).getStatus()); + assertEquals("pieceId2", result.getClaimingPieceResults().get(1).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, result.getClaimingPieceResults().get(1).getStatus()); + testContext.completeNow(); + }))); + } + + @Test + void testSendClaims_successWithMultipleOrganizations(VertxTestContext testContext) { + var claimingCollection = new ClaimingCollection().withClaimingPieceIds(List.of("pieceId1", "pieceId2", "pieceId3", "pieceId4", "pieceId5")); + var requestContext = mock(RequestContext.class); + + when(configurationEntriesCache.loadConfiguration(any(), any())).thenReturn(Future.succeededFuture(new JsonObject() + .put("CLAIMS_vendorId1", createIntegrationDetail()) + .put("CLAIMS_vendorId2", createIntegrationDetail()))); + + when(pieceStorageService.getPiecesByIds(any(), any())).thenReturn(Future.succeededFuture(List.of( + new Piece().withId("pieceId1").withPoLineId("poLineId1").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId2").withPoLineId("poLineId2").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId3").withPoLineId("poLineId3").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId4").withPoLineId("poLineId4").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId5").withPoLineId("poLineId5").withReceivingStatus(Piece.ReceivingStatus.LATE) + ))); + + when(purchaseOrderLineService.getOrderLineById(any(), any())).thenAnswer(invocation -> { + String poLineId = invocation.getArgument(0); + return Future.succeededFuture(new PoLine().withPurchaseOrderId(poLineId.startsWith("poLineId1") || poLineId.startsWith("poLineId2") ? "orderId1" : "orderId2")); + }); + + when(purchaseOrderStorageService.getPurchaseOrderById(any(), any())).thenAnswer(invocation -> { + String orderId = invocation.getArgument(0); + return Future.succeededFuture(new PurchaseOrder().withVendor(orderId.equals("orderId1") ? "vendorId1" : "vendorId2")); + }); + + when(organizationService.getVendorById(any(), any())).thenAnswer(invocation -> { + String vendorId = invocation.getArgument(0); + return Future.succeededFuture(new Organization().withId(vendorId).withIsVendor(true)); + }); + + when(pieceUpdateFlowManager.updatePiecesStatuses(any(), any(), any())).thenReturn(Future.succeededFuture()); + when(restClient.post(eq(resourcesPath(DATA_EXPORT_SPRING_CREATE_JOB)), any(), any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("status", "CREATED"))); + when(restClient.postEmptyResponse(any(), any(), any())).thenReturn(Future.succeededFuture()); + + piecesClaimingService.sendClaims(claimingCollection, requestContext) + .onComplete(testContext.succeeding(result -> testContext.verify(() -> { + assertEquals(5, result.getClaimingPieceResults().size()); + var copiedSortedResults = new ArrayList<>(result.getClaimingPieceResults()); + copiedSortedResults.sort(Comparator.comparing(ClaimingPieceResult::getPieceId)); + assertEquals("pieceId1", copiedSortedResults.get(0).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, copiedSortedResults.get(0).getStatus()); + assertEquals("pieceId2", copiedSortedResults.get(1).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, copiedSortedResults.get(1).getStatus()); + assertEquals("pieceId3", copiedSortedResults.get(2).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, copiedSortedResults.get(2).getStatus()); + assertEquals("pieceId4", copiedSortedResults.get(3).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, copiedSortedResults.get(3).getStatus()); + assertEquals("pieceId5", copiedSortedResults.get(4).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, copiedSortedResults.get(4).getStatus()); + testContext.completeNow(); + }))); + } + + @Test + void testSendClaims_successWithMultipleOrganizationsAndOneIntegrationDetail(VertxTestContext testContext) { + var claimingCollection = new ClaimingCollection().withClaimingPieceIds(List.of("pieceId1", "pieceId2", "pieceId3", "pieceId4", "pieceId5")); + var requestContext = mock(RequestContext.class); + + when(configurationEntriesCache.loadConfiguration(any(), any())).thenReturn(Future.succeededFuture(new JsonObject() + .put("CLAIMS_vendorId1", createIntegrationDetail()))); + + when(pieceStorageService.getPiecesByIds(any(), any())).thenReturn(Future.succeededFuture(List.of( + new Piece().withId("pieceId1").withPoLineId("poLineId1").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId2").withPoLineId("poLineId2").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId3").withPoLineId("poLineId3").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId4").withPoLineId("poLineId4").withReceivingStatus(Piece.ReceivingStatus.LATE), + new Piece().withId("pieceId5").withPoLineId("poLineId5").withReceivingStatus(Piece.ReceivingStatus.LATE) + ))); + + when(purchaseOrderLineService.getOrderLineById(any(), any())).thenAnswer(invocation -> { + String poLineId = invocation.getArgument(0); + return Future.succeededFuture(new PoLine().withPurchaseOrderId(poLineId.startsWith("poLineId1") || poLineId.startsWith("poLineId2") ? "orderId1" : "orderId2")); + }); + + when(purchaseOrderStorageService.getPurchaseOrderById(any(), any())).thenAnswer(invocation -> { + String orderId = invocation.getArgument(0); + return Future.succeededFuture(new PurchaseOrder().withVendor(orderId.equals("orderId1") ? "vendorId1" : "vendorId2")); + }); + + when(organizationService.getVendorById(any(), any())).thenAnswer(invocation -> { + String vendorId = invocation.getArgument(0); + return Future.succeededFuture(new Organization().withId(vendorId).withIsVendor(true)); + }); + + when(pieceUpdateFlowManager.updatePiecesStatuses(any(), any(), any())).thenReturn(Future.succeededFuture()); + when(restClient.post(eq(resourcesPath(DATA_EXPORT_SPRING_CREATE_JOB)), any(), any(), any())).thenReturn(Future.succeededFuture(new JsonObject().put("status", "CREATED"))); + when(restClient.postEmptyResponse(any(), any(), any())).thenReturn(Future.succeededFuture()); + + piecesClaimingService.sendClaims(claimingCollection, requestContext) + .onComplete(testContext.succeeding(result -> testContext.verify(() -> { + assertEquals(2, result.getClaimingPieceResults().size()); + var copiedSortedResults = new ArrayList<>(result.getClaimingPieceResults()); + copiedSortedResults.sort(Comparator.comparing(ClaimingPieceResult::getPieceId)); + assertEquals("pieceId1", copiedSortedResults.get(0).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, copiedSortedResults.get(0).getStatus()); + assertEquals("pieceId2", copiedSortedResults.get(1).getPieceId()); + assertEquals(ClaimingPieceResult.Status.SUCCESS, copiedSortedResults.get(1).getStatus()); + testContext.completeNow(); + }))); + } + + private JsonObject createIntegrationDetail() { + var vendorEditOrdersExportConfig = new JsonObject().put(CLAIM_PIECE_IDS.getValue(), List.of()); + var exportTypeSpecificParameters = new JsonObject().put(VENDOR_EDI_ORDERS_EXPORT_CONFIG.getValue(), vendorEditOrdersExportConfig); + return new JsonObject().put(EXPORT_TYPE_SPECIFIC_PARAMETERS.getValue(), exportTypeSpecificParameters); + } +} diff --git a/src/test/resources/log4j2-test.properties b/src/test/resources/log4j2-test.properties index cc7e68306..567bcb891 100644 --- a/src/test/resources/log4j2-test.properties +++ b/src/test/resources/log4j2-test.properties @@ -1,11 +1,11 @@ -status = debug +status = info name = PropertiesConfig 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} [$${FolioLoggingContext:requestid}] [$${FolioLoggingContext:tenantid}] [$${FolioLoggingContext:userid}] [$${FolioLoggingContext:moduleid}] %-5p %-20.40C{1} %m%n -rootLogger.level = debug +rootLogger.level = info rootLogger.appenderRefs = info rootLogger.appenderRef.stdout.ref = STDOUT diff --git a/src/test/resources/mockdata/claiming/send-claims-1-piece-1-vendor-1-job.json b/src/test/resources/mockdata/claiming/send-claims-1-piece-1-vendor-1-job.json new file mode 100644 index 000000000..090aad6b5 --- /dev/null +++ b/src/test/resources/mockdata/claiming/send-claims-1-piece-1-vendor-1-job.json @@ -0,0 +1,5 @@ +{ + "claimingPieceIds": [ + "dcd0ba36-b660-4751-b9fe-c8ac61ff6f99" + ] +} diff --git a/src/test/resources/mockdata/configurations.entries/test_diku_limit_10_claims.json b/src/test/resources/mockdata/configurations.entries/test_diku_limit_10_claims.json new file mode 100644 index 000000000..833dd24b7 --- /dev/null +++ b/src/test/resources/mockdata/configurations.entries/test_diku_limit_10_claims.json @@ -0,0 +1,94 @@ +{ + "configs": [ + { + "id": "e3a73e91-aac9-40a4-8f47-b0187bdb1e6b", + "module": "ORDERS", + "configName": "poLines-limit", + "enabled": true, + "value": "10", + "metadata": { + "createdDate": "2018-12-12T08:14:32.743+0000", + "createdByUserId": "d16d7615-ad6b-5a57-9cb4-62aca2ba764c", + "updatedDate": "2018-12-12T08:24:34.213+0000", + "updatedByUserId": "d16d7615-ad6b-5a57-9cb4-62aca2ba764c" + } + }, + { + "id": "d16d7615-ad6b-5a57-9cb4-62aca2ba764c", + "module": "ORDERS", + "configName": "createInventory", + "enabled": true, + "value": "{\"eresource\":\"Instance, Holding, Item\",\"physical\":\"Instance, Holding, Item\",\"other\":\"Instance, Holding, Item\"}", + "metadata": { + "createdDate": "2018-12-12T08:14:32.743+0000", + "createdByUserId": "d16d7615-ad6b-5a57-9cb4-62aca2ba764c", + "updatedDate": "2018-12-12T08:24:34.213+0000", + "updatedByUserId": "d16d7615-ad6b-5a57-9cb4-62aca2ba764c" + } + }, + { + "id": "e48f35bd-1dea-4993-ad3c-dfa7ae668c80", + "code": "ADDRESS_12345", + "module": "TENANT", + "configName": "addresses", + "enabled": true, + "value": "{\n \"address\": \"sample address\",\n \"name\": \"sample name\"\n}\n", + "metadata": { + "createdDate": "2018-12-12T08:14:32.743+0000", + "createdByUserId": "d16d7615-ad6b-5a57-9cb4-62aca2ba764c", + "updatedDate": "2018-12-12T08:24:34.213+0000", + "updatedByUserId": "d16d7615-ad6b-5a57-9cb4-62aca2ba764c" + } + }, + { + "id": "5534ca06-b395-41b3-9bfa-8df54bc93800", + "module": "ORDERS", + "configName": "inventory-instanceTypeCode", + "enabled": true, + "value": "customInstanceType" + }, + { + "id": "5fd9dea2-57b0-43e1-951d-dc460fa63622", + "module": "ORDERS", + "configName": "inventory-instanceStatusCode", + "enabled": true, + "value": "customInstanceStatus" + }, + { + "id": "c19bf0dd-0d82-4c6e-9ff0-774568f937de", + "module": "ORDERS", + "configName": "inventory-loanTypeName", + "enabled": true, + "value": "customLoanType" + }, + { + "id" : "339bc2b6-4f2d-4fff-a23c-4fbec2a5e27a", + "module" : "ORDERS", + "configName" : "approvals", + "enabled" : true, + "value" : "{\"isApprovalRequired\":false}" + }, + { + "id" : "582ac200-1793-4015-ad80-4dc4b2a1ea82", + "module" : "ORG", + "configName" : "localeSettings", + "enabled" : true, + "value" : "{\"locale\":\"en-US\",\"timezone\":\"UTC\",\"currency\":\"USD\"}" + }, + { + "id": "245bc212-4e56-4875-8c84-4401018d4242", + "value": "{\"id\":\"245bc212-4e56-4875-8c84-4401018d4242\",\"type\":\"CLAIMS\",\"tenant\":\"diku\",\"exportTypeSpecificParameters\":{\"vendorEdiOrdersExportConfig\":{\"exportConfigId\":\"245bc212-4e56-4875-8c84-4401018d4242\",\"vendorId\":\"e0fb5df2-cdf1-11e8-a8d5-f2801f1b9fd1\",\"integrationType\":\"Claiming\",\"transmissionMethod\":\"File download\",\"fileFormat\":\"CSV\",\"configName\":\"Test 1\",\"ediConfig\":{\"accountNoList\":[\"1\"],\"ediNamingConvention\":\"{organizationCode}-{integrationName}-{exportJobEndDate}\",\"libEdiCode\":\"Test 1\",\"libEdiType\":\"31B/US-SAN\",\"vendorEdiCode\":\"Test 1\",\"vendorEdiType\":\"31B/US-SAN\",\"sendAccountNumber\":false,\"supportOrder\":false,\"supportInvoice\":false},\"ediFtp\":{\"ftpConnMode\":\"Active\",\"ftpFormat\":\"SFTP\",\"ftpMode\":\"ASCII\",\"ftpPort\":1,\"serverAddress\":\"ftp://test1.org\"},\"isDefaultConfig\":false}},\"schedulePeriod\":\"NONE\"}", + "module": "mod-data-export-spring", + "default": true, + "enabled": true, + "metadata": { + "createdDate": "2024-11-28T10:45:25.523Z", + "updatedDate": "2024-11-28T10:45:25.523Z", + "createdByUserId": "d77db61a-4404-4cab-9125-0c3a3567a9b0", + "updatedByUserId": "d77db61a-4404-4cab-9125-0c3a3567a9b0" + }, + "configName": "CLAIMS_e0fb5df2-cdf1-11e8-a8d5-f2801f1b9fd1_245bc212-4e56-4875-8c84-4401018d4242", + "description": "Claims configuration parameters" + } + ] +} diff --git a/src/test/resources/mockdata/lines/428c60e8-c43d-4543-b0d4-36dada430e51.json b/src/test/resources/mockdata/lines/428c60e8-c43d-4543-b0d4-36dada430e51.json new file mode 100644 index 000000000..c47637bed --- /dev/null +++ b/src/test/resources/mockdata/lines/428c60e8-c43d-4543-b0d4-36dada430e51.json @@ -0,0 +1,60 @@ +{ + "id": "428c60e8-c43d-4543-b0d4-36dada430e51", + "cost": { + "currency": "USD", + "discountType": "percentage", + "listUnitPrice": 1.0, + "quantityPhysical": 1, + "poLineEstimatedPrice": 1.0 + }, + "rush": false, + "alerts": [], + "claims": [], + "source": "User", + "details": { + "productIds": [], + "isAcknowledged": false, + "isBinderyActive": false, + "subscriptionInterval": 0 + }, + "physical": { + "volumes": [], + "materialType": "1a54b431-2e4f-452d-9cae-9cee66c9a892", + "createInventory": "Instance, Holding, Item", + "materialSupplier": "e0fb5df2-cdf1-11e8-a8d5-f2801f1b9fd1" + }, + "isPackage": false, + "locations": [ + { + "quantity": 1, + "holdingId": "f845d96f-5d1d-4757-81a8-2066f233836a", + "quantityPhysical": 1 + } + ], + "collection": false, + "instanceId": "d7ee00ec-c456-497e-b330-d93c629acf9e", + "orderFormat": "Physical Resource", + "checkinItems": false, + "contributors": [], + "poLineNumber": "10003-1", + "vendorDetail": { + "instructions": "", + "vendorAccount": "1234", + "referenceNumbers": [] + }, + "paymentStatus": "Awaiting Payment", + "receiptStatus": "Awaiting Receipt", + "claimingActive": false, + "reportingCodes": [], + "titleOrPackage": "Test 4", + "automaticExport": false, + "purchaseOrderId": "64d15f49-3bbe-45a3-9e7d-fe2117dc4458", + "claimingInterval": 45, + "fundDistribution": [], + "acquisitionMethod": "306489dd-0053-49ee-a068-c316444a8f55", + "searchLocationIds": [ + "fcd64ce1-6995-48f0-840e-89ffa2288371" + ], + "donorOrganizationIds": [], + "cancellationRestriction": true +} diff --git a/src/test/resources/mockdata/lines/po_line_collection.json b/src/test/resources/mockdata/lines/po_line_collection.json index 607916257..4dde1193a 100644 --- a/src/test/resources/mockdata/lines/po_line_collection.json +++ b/src/test/resources/mockdata/lines/po_line_collection.json @@ -1395,7 +1395,67 @@ ], "donorOrganizationIds": [], "cancellationRestriction": true + }, + { + "id": "428c60e8-c43d-4543-b0d4-36dada430e51", + "cost": { + "currency": "USD", + "discountType": "percentage", + "listUnitPrice": 1.0, + "quantityPhysical": 1, + "poLineEstimatedPrice": 1.0 + }, + "rush": false, + "alerts": [], + "claims": [], + "source": "User", + "details": { + "productIds": [], + "isAcknowledged": false, + "isBinderyActive": false, + "subscriptionInterval": 0 + }, + "physical": { + "volumes": [], + "materialType": "1a54b431-2e4f-452d-9cae-9cee66c9a892", + "createInventory": "Instance, Holding, Item", + "materialSupplier": "e0fb5df2-cdf1-11e8-a8d5-f2801f1b9fd1" + }, + "isPackage": false, + "locations": [ + { + "quantity": 1, + "holdingId": "f845d96f-5d1d-4757-81a8-2066f233836a", + "quantityPhysical": 1 + } + ], + "collection": false, + "instanceId": "d7ee00ec-c456-497e-b330-d93c629acf9e", + "orderFormat": "Physical Resource", + "checkinItems": false, + "contributors": [], + "poLineNumber": "10003-1", + "vendorDetail": { + "instructions": "", + "vendorAccount": "1234", + "referenceNumbers": [] + }, + "paymentStatus": "Awaiting Payment", + "receiptStatus": "Awaiting Receipt", + "claimingActive": false, + "reportingCodes": [], + "titleOrPackage": "Test 4", + "automaticExport": false, + "purchaseOrderId": "64d15f49-3bbe-45a3-9e7d-fe2117dc4458", + "claimingInterval": 45, + "fundDistribution": [], + "acquisitionMethod": "306489dd-0053-49ee-a068-c316444a8f55", + "searchLocationIds": [ + "fcd64ce1-6995-48f0-840e-89ffa2288371" + ], + "donorOrganizationIds": [], + "cancellationRestriction": true } ], - "totalRecords": 17 + "totalRecords": 18 } diff --git a/src/test/resources/mockdata/organizations/organizations.json b/src/test/resources/mockdata/organizations/organizations.json new file mode 100644 index 000000000..8d1e50a2e --- /dev/null +++ b/src/test/resources/mockdata/organizations/organizations.json @@ -0,0 +1,139 @@ +{ + "organizations": [ + { + "id": "e0fb5df2-cdf1-11e8-a8d5-f2801f1b9fd1", + "code": "AMAZ", + "name": "Amazon.com", + "urls": [ + { + "notes": "", + "value": "https://www.amazon.com", + "language": "en-us", + "isPrimary": true, + "categories": [ + "f52ceea4-8e35-404b-9ebd-5c7db6613195" + ], + "description": "main website" + } + ], + "taxId": "", + "emails": [ + { + "value": "cust.service03@amazon.com", + "language": "English", + "isPrimary": true, + "categories": [], + "description": "customer service" + } + ], + "status": "Active", + "aliases": [ + { + "value": "Amazon", + "description": "" + } + ], + "erpCode": "G64758-74834", + "isDonor": false, + "sanCode": "1234567", + "accounts": [ + { + "name": "Monographic ordering unit account", + "notes": "", + "accountNo": "1234", + "acqUnitIds": [], + "appSystemNo": "", + "contactInfo": "cust.service03@amazon.com", + "description": "Monographic ordering unit account", + "libraryCode": "COB", + "accountStatus": "Active", + "paymentMethod": "Credit Card", + "libraryEdiCode": "765987610" + }, + { + "name": "Test 1", + "accountNo": "1", + "acqUnitIds": [], + "accountStatus": "Active" + }, + { + "name": "Test 2", + "accountNo": "2", + "acqUnitIds": [], + "accountStatus": "Active" + } + ], + "contacts": [ + "e0fb5df2-cdf1-11e8-a8d5-f2801f1b9fd1" + ], + "isVendor": true, + "language": "en-us", + "licensor": false, + "metadata": { + "createdDate": "2024-11-28T05:19:54.699Z", + "updatedDate": "2024-11-28T10:44:52.154Z", + "updatedByUserId": "d77db61a-4404-4cab-9125-0c3a3567a9b0" + }, + "addresses": [ + { + "city": "New Castle", + "country": "USA", + "zipCode": "19720-5550", + "language": "English", + "isPrimary": true, + "categories": [], + "stateRegion": "DE", + "addressLine1": "1 Centerpiece Blvd.", + "addressLine2": "P.O. Box 15550" + } + ], + "acqUnitIds": [], + "agreements": [ + { + "name": "test", + "notes": "", + "discount": 0.0, + "referenceUrl": "" + } + ], + "changelogs": [ + { + "timestamp": "2008-05-15T10:53:00.000+00:00", + "description": "This is a sample note." + } + ], + "interfaces": [ + "cd592659-77aa-4eb3-ac34-c9a4657bb20f" + ], + "description": "Use for rush orders, replacement requests, and second hand market", + "governmental": false, + "liableForVat": false, + "phoneNumbers": [ + { + "language": "English", + "isPrimary": true, + "categories": [], + "phoneNumber": "1-888-238-22090" + } + ], + "paymentMethod": "Credit Card", + "taxPercentage": 0.0, + "accessProvider": false, + "discountPercent": 0.0, + "claimingInterval": 45, + "materialSupplier": true, + "vendorCurrencies": [ + "USD" + ], + "organizationTypes": [], + "exportToAccounting": true, + "privilegedContacts": [], + "subscriptionInterval": 0, + "expectedInvoiceInterval": 0, + "expectedReceiptInterval": 30, + "renewalActivationInterval": 0, + "expectedActivationInterval": 0 + } + ], + "totalRecords": 1 +} diff --git a/src/test/resources/mockdata/pieces/pieceRecord-dcd0ba36-b660-4751-b9fe-c8ac61ff6f99.json b/src/test/resources/mockdata/pieces/pieceRecord-dcd0ba36-b660-4751-b9fe-c8ac61ff6f99.json new file mode 100644 index 000000000..3a2d9b709 --- /dev/null +++ b/src/test/resources/mockdata/pieces/pieceRecord-dcd0ba36-b660-4751-b9fe-c8ac61ff6f99.json @@ -0,0 +1,13 @@ +{ + "id": "dcd0ba36-b660-4751-b9fe-c8ac61ff6f99", + "format": "Physical", + "itemId": "c43e0be8-e12e-4bed-81ba-58031bcd832e", + "isBound": false, + "titleId": "5f525419-da33-4731-9a19-0c59a371336f", + "poLineId": "428c60e8-c43d-4543-b0d4-36dada430e51", + "holdingId": "f845d96f-5d1d-4757-81a8-2066f233836a", + "displayToPublic": false, + "receivingStatus": "Late", + "displayOnHolding": false, + "statusUpdatedDate": "2024-11-28T11:28:52.523+00:00" +} diff --git a/src/test/resources/mockdata/pieces/pieceRecordsCollection.json b/src/test/resources/mockdata/pieces/pieceRecordsCollection.json index 832424d01..ea524209c 100644 --- a/src/test/resources/mockdata/pieces/pieceRecordsCollection.json +++ b/src/test/resources/mockdata/pieces/pieceRecordsCollection.json @@ -623,7 +623,20 @@ "displayOnHolding": true, "discoverySuppress": false, "statusUpdatedDate": "2024-09-06T13:33:34.267+00:00" + }, + { + "id": "dcd0ba36-b660-4751-b9fe-c8ac61ff6f99", + "format": "Physical", + "itemId": "c43e0be8-e12e-4bed-81ba-58031bcd832e", + "isBound": false, + "titleId": "5f525419-da33-4731-9a19-0c59a371336f", + "poLineId": "428c60e8-c43d-4543-b0d4-36dada430e51", + "holdingId": "f845d96f-5d1d-4757-81a8-2066f233836a", + "displayToPublic": false, + "receivingStatus": "Late", + "displayOnHolding": false, + "statusUpdatedDate": "2024-11-28T11:28:52.523+00:00" } ], - "totalRecords": 69 + "totalRecords": 70 }