From 17bf8743a5824403964f32d93ea4b7f4a606fb38 Mon Sep 17 00:00:00 2001 From: saba_zedginidze Date: Thu, 19 Sep 2024 15:52:47 +0400 Subject: [PATCH 01/11] [MODORDERS-1143] Refactor existing code --- .../folio/helper/PurchaseOrderLineHelper.java | 438 +++++++----------- .../folio/models/PoLineInvoiceLineHolder.java | 6 +- .../PoLineInvoiceLineHolderBuilder.java | 3 +- .../service/orders/utils/StatusUtils.java | 53 +++ 4 files changed, 233 insertions(+), 267 deletions(-) create mode 100644 src/main/java/org/folio/service/orders/utils/StatusUtils.java diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index 7dcc2cafc..7e68a53c5 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -3,9 +3,7 @@ import static io.vertx.core.json.JsonObject.mapFrom; import static org.apache.commons.collections4.CollectionUtils.isEqualCollection; import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; -import static org.apache.commons.lang3.StringUtils.isEmpty; -import static org.folio.helper.BaseHelper.EVENT_PAYLOAD; -import static org.folio.helper.BaseHelper.ORDER_ID; +import static org.apache.commons.collections4.CollectionUtils.isEmpty; import static org.folio.orders.utils.HelperUtils.calculateEstimatedPrice; import static org.folio.orders.utils.HelperUtils.getPoLineLimit; import static org.folio.orders.utils.PoLineCommonUtil.verifyProtectedFieldsChanged; @@ -20,6 +18,10 @@ import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.CLOSED; import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.OPEN; import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.PENDING; +import static org.folio.service.orders.utils.StatusUtils.areAllPoLinesCanceled; +import static org.folio.service.orders.utils.StatusUtils.isPoLineStatusCanceled; +import static org.folio.service.orders.utils.StatusUtils.isStatusChanged; +import static org.folio.service.orders.utils.StatusUtils.updateOrderStatusIfNeeded; import java.util.ArrayList; import java.util.Collections; @@ -28,7 +30,6 @@ import java.util.Optional; import java.util.UUID; import java.util.Objects; -import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; @@ -42,7 +43,6 @@ import org.folio.models.ItemStatus; import org.folio.models.PoLineInvoiceLineHolder; import org.folio.okapi.common.GenericCompositeFuture; -import org.folio.orders.events.handlers.MessageAddress; import org.folio.orders.utils.HelperUtils; import org.folio.orders.utils.POLineProtectedFieldsUtil; import org.folio.orders.utils.PoLineCommonUtil; @@ -67,7 +67,6 @@ import org.folio.rest.jaxrs.model.PoLine; import org.folio.rest.jaxrs.model.PoLineCollection; import org.folio.rest.jaxrs.model.ReportingCode; -import org.folio.rest.jaxrs.model.Title; import org.folio.service.ProtectionService; import org.folio.service.finance.expenceclass.ExpenseClassValidationService; import org.folio.service.finance.transaction.EncumbranceService; @@ -87,7 +86,6 @@ import io.vertx.core.Future; import io.vertx.core.Promise; import io.vertx.core.http.HttpMethod; -import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; public class PurchaseOrderLineHelper { @@ -96,7 +94,6 @@ public class PurchaseOrderLineHelper { private static final Pattern PO_LINE_NUMBER_PATTERN = Pattern.compile("([a-zA-Z0-9]{1,22}-)(\\d{1,3})"); private static final String PURCHASE_ORDER_ID = "purchaseOrderId"; - private static final String SEARCH_LOCATION_IDS = "searchLocationIds"; private static final String CREATE_INVENTORY = "createInventory"; public static final String ERESOURCE = "eresource"; public static final String PHYSICAL = "physical"; @@ -177,24 +174,23 @@ public Future getOrderLines(int limit, int offset, String quer */ public Future createPoLine(CompositePoLine compPOL, JsonObject tenantConfig, RequestContext requestContext) { // Validate PO Line content and retrieve order only if this operation is allowed - JsonObject cachedTenantConfiguration= new JsonObject(); + JsonObject cachedTenantConfiguration = new JsonObject(); cachedTenantConfiguration.mergeIn(tenantConfig, true); - return setTenantDefaultCreateInventoryValues(compPOL, cachedTenantConfiguration) + return setTenantDefaultCreateInventoryValues(compPOL, cachedTenantConfiguration) .compose(v -> validateNewPoLine(compPOL, cachedTenantConfiguration, requestContext)) .compose(validationErrors -> { - if (CollectionUtils.isEmpty(validationErrors)) { + if (isEmpty(validationErrors)) { return getCompositePurchaseOrder(compPOL.getPurchaseOrderId(), requestContext) // The PO Line can be created only for order in Pending state .map(this::validateOrderState) .compose(po -> protectionService.isOperationRestricted(po.getAcqUnitIds(), ProtectedOperationType.CREATE, requestContext) - .compose(v -> createShadowInstanceIfNeeded(compPOL, requestContext)) - .compose(v -> createPoLineWithOrder(compPOL, po, requestContext))); - } else { - Errors errors = new Errors().withErrors(validationErrors).withTotalRecords(validationErrors.size()); - logger.error("Create POL validation error : {}", JsonObject.mapFrom(errors).encodePrettily()); - throw new HttpException(RestConstants.VALIDATION_ERROR, errors); + .compose(v -> createShadowInstanceIfNeeded(compPOL, requestContext)) + .compose(v -> createPoLineWithOrder(compPOL, po, requestContext))); } + var errors = new Errors().withErrors(validationErrors).withTotalRecords(validationErrors.size()); + logger.error("Create POL validation error : {}", JsonObject.mapFrom(errors).encodePrettily()); + throw new HttpException(RestConstants.VALIDATION_ERROR, errors); }); } @@ -204,48 +200,44 @@ public Future createPoLine(CompositePoLine compPOL, JsonObject * @param compOrder associated {@link CompositePurchaseOrder} object * @return completable future which might hold {@link CompositePoLine} on success or an exception if any issue happens */ - public Future createPoLineWithOrder(CompositePoLine compPoLine, CompositePurchaseOrder compOrder, - RequestContext requestContext) { + public Future createPoLineWithOrder(CompositePoLine compPoLine, CompositePurchaseOrder compOrder, RequestContext requestContext) { // The id is required because sub-objects are being created first - if (isEmpty(compPoLine.getId())) { + if (StringUtils.isEmpty(compPoLine.getId())) { compPoLine.setId(UUID.randomUUID().toString()); } compPoLine.setPurchaseOrderId(compOrder.getId()); updateEstimatedPrice(compPoLine); PoLineCommonUtil.updateLocationsQuantity(compPoLine.getLocations()); - JsonObject line = mapFrom(compPoLine); + var line = mapFrom(compPoLine).mapTo(PoLine.class); List> subObjFuts = new ArrayList<>(); - subObjFuts.add(createAlerts(compPoLine, line, requestContext)); subObjFuts.add(createReportingCodes(compPoLine, line, requestContext)); return GenericCompositeFuture.join(new ArrayList<>(subObjFuts)) .compose(v -> generateLineNumber(compOrder, requestContext)) - .map(lineNumber -> line.put(PO_LINE_NUMBER, lineNumber)) + .map(line::withPoLineNumber) .compose(v -> purchaseOrderLineService.updateSearchLocations(compPoLine, requestContext)) - .map(v -> line.put(SEARCH_LOCATION_IDS, compPoLine.getSearchLocationIds())) + .map(v -> line.withSearchLocationIds(compPoLine.getSearchLocationIds())) .compose(v -> createPoLineSummary(compPoLine, line, requestContext)); } public Future setTenantDefaultCreateInventoryValues(CompositePoLine compPOL, JsonObject tenantConfiguration) { - Promise promise = Promise.promise(); + if (!isCreateInventoryNull(compPOL)) { + return Future.succeededFuture(); + } - if (isCreateInventoryNull(compPOL)) { - if (tenantConfiguration != null && !tenantConfiguration.isEmpty() && - StringUtils.isNotEmpty(tenantConfiguration.getString(CREATE_INVENTORY))) { - promise.complete(new JsonObject(tenantConfiguration.getString(CREATE_INVENTORY))); - } else { - promise.complete(new JsonObject()); - } - return promise.future() - .map(jsonConfig -> { - updateCreateInventory(compPOL, jsonConfig); - return null; - }); + Promise promise = Promise.promise(); + if (tenantConfiguration != null && !tenantConfiguration.isEmpty() && !StringUtils.isEmpty(tenantConfiguration.getString(CREATE_INVENTORY))) { + promise.complete(new JsonObject(tenantConfiguration.getString(CREATE_INVENTORY))); } else { - return Future.succeededFuture(); + promise.complete(new JsonObject()); } + return promise.future() + .map(jsonConfig -> { + updateCreateInventory(compPOL, jsonConfig); + return null; + }); } public static boolean isCreateInventoryNull(CompositePoLine compPOL) { @@ -256,11 +248,11 @@ public static boolean isCreateInventoryNull(CompositePoLine compPOL) { }; } - public Future getCompositePoLine(String polineId, RequestContext requestContext) { - return purchaseOrderLineService.getOrderLineById(polineId, requestContext) + public Future getCompositePoLine(String poLineId, RequestContext requestContext) { + return purchaseOrderLineService.getOrderLineById(poLineId, requestContext) .compose(line -> getCompositePurchaseOrder(line.getPurchaseOrderId(), requestContext) .compose(order -> protectionService.isOperationRestricted(order.getAcqUnitIds(), ProtectedOperationType.READ, requestContext)) - .compose(ok -> populateCompositeLine(line, requestContext))); + .compose(v -> populateCompositeLine(line, requestContext))); } public Future deleteLine(String lineId, RequestContext requestContext) { @@ -270,8 +262,8 @@ public Future deleteLine(String lineId, RequestContext requestContext) { logger.debug("Deleting PO line..."); return encumbranceService.deletePoLineEncumbrances(line, requestContext) .compose(v -> purchaseOrderLineService.deletePoLine(line, requestContext)); - })) - .onSuccess(json -> logger.info("The PO Line with id='{}' has been deleted successfully", lineId)); + })) + .onSuccess(json -> logger.info("deleteLine:: PoLine with id='{}' has been deleted successfully", lineId)); } /** @@ -279,54 +271,45 @@ public Future deleteLine(String lineId, RequestContext requestContext) { */ public Future updateOrderLine(CompositePoLine compOrderLine, RequestContext requestContext) { return getPoLineByIdAndValidate(compOrderLine.getPurchaseOrderId(), compOrderLine.getId(), requestContext) - .compose(lineFromStorage -> getCompositePurchaseOrder(compOrderLine.getPurchaseOrderId(), requestContext) - .map(compOrder -> addLineToCompOrder(compOrder, lineFromStorage)) + .compose(lineFromStorage -> { + var poLineFromStorage = lineFromStorage.mapTo(PoLine.class); + return getCompositePurchaseOrder(compOrderLine.getPurchaseOrderId(), requestContext) + .map(compOrder -> addLineToCompOrder(compOrder, poLineFromStorage)) .map(compOrder -> { - validatePOLineProtectedFieldsChanged(compOrderLine, lineFromStorage, compOrder); + validatePOLineProtectedFieldsChanged(compOrderLine, poLineFromStorage, compOrder); PoLineCommonUtil.updateLocationsQuantity(compOrderLine.getLocations()); updateEstimatedPrice(compOrderLine); - checkLocationCanBeModified(compOrderLine, lineFromStorage.mapTo(PoLine.class), compOrder); + checkLocationCanBeModified(compOrderLine, poLineFromStorage, compOrder); return compOrder; }) - .compose(compOrder -> protectionService.isOperationRestricted(compOrder.getAcqUnitIds(), UPDATE, requestContext) - .compose(v -> purchaseOrderLineService.validateAndNormalizeISBNAndProductType(Collections.singletonList(compOrderLine), requestContext)) - .compose(v -> validateAccessProviders(compOrderLine, requestContext)) - .compose(v -> expenseClassValidationService.validateExpenseClassesForOpenedOrder(compOrder, Collections.singletonList(compOrderLine), requestContext)) - .compose(v -> processPoLineEncumbrances(compOrder, compOrderLine, lineFromStorage, requestContext)) - .map(v -> lineFromStorage))) - .compose(lineFromStorage -> { - // override PO line number in the request with one from the storage, because it's not allowed to change it during PO line - // update - PoLineInvoiceLineHolder poLineInvoiceLineHolder = new PoLineInvoiceLineHolder(compOrderLine, lineFromStorage); - compOrderLine.setPoLineNumber(lineFromStorage.getString(PO_LINE_NUMBER)); - - return polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext) + .compose(compOrder -> protectionService.isOperationRestricted(compOrder.getAcqUnitIds(), UPDATE, requestContext) + .compose(v -> purchaseOrderLineService.validateAndNormalizeISBNAndProductType(Collections.singletonList(compOrderLine), requestContext)) + .compose(v -> validateAccessProviders(compOrderLine, requestContext)) + .compose(v -> expenseClassValidationService.validateExpenseClassesForOpenedOrder(compOrder, Collections.singletonList(compOrderLine), requestContext)) + .compose(v -> processPoLineEncumbrances(compOrder, compOrderLine, poLineFromStorage, requestContext))) + .map(v -> compOrderLine.withPoLineNumber(poLineFromStorage.getPoLineNumber())) // PoLine number must not be modified during PoLine update, set original value + .map(v -> new PoLineInvoiceLineHolder(compOrderLine, poLineFromStorage)) + .compose(poLineInvoiceLineHolder -> polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext) .compose(v -> createShadowInstanceIfNeeded(compOrderLine, requestContext)) .compose(v -> updateOrderLine(compOrderLine, lineFromStorage, requestContext)) - .compose(v -> updateEncumbranceStatus(compOrderLine, lineFromStorage, requestContext)) + .compose(v -> updateEncumbranceStatus(compOrderLine, poLineFromStorage, requestContext)) .compose(v -> polInvoiceLineRelationService.updateInvoiceLineReference(poLineInvoiceLineHolder, requestContext)) - .compose(v -> updateInventoryItemStatus(compOrderLine, lineFromStorage, requestContext)) - .map(ok -> { - updateOrderStatus(compOrderLine, lineFromStorage, requestContext); - return null; - }); - }); - - } - - private Future updateEncumbranceStatus(CompositePoLine compOrderLine, JsonObject lineFromStorage, - RequestContext requestContext) { - PoLine poLine = lineFromStorage.mapTo(PoLine.class); - if (isReleaseEncumbrances(compOrderLine, poLine)) { - logger.info("Encumbrances releasing for poLineId={} where paymentStatus={}", compOrderLine.getId(), compOrderLine.getPaymentStatus()); - return encumbranceService.getPoLineUnreleasedEncumbrances(compOrderLine, requestContext) - .compose(transactionList -> encumbranceService.releaseEncumbrances(transactionList, requestContext)); - } else if (isUnreleasedEncumbrances(compOrderLine, poLine)) { - logger.info("Encumbrances unreleasing for poLineId={} where paymentStatus={}", compOrderLine.getId(), compOrderLine.getPaymentStatus()); - return encumbranceService.getPoLineReleasedEncumbrances(compOrderLine, requestContext) - .compose(transactionList -> encumbranceService.unreleaseEncumbrances(transactionList, requestContext)); - } - return Future.succeededFuture(); + .compose(v -> updateInventoryItemStatus(compOrderLine, poLineFromStorage, requestContext)) + .compose(v -> updateOrderStatusIfNeeded(compOrderLine, lineFromStorage, requestContext))); + }); + } + + private Future updateEncumbranceStatus(CompositePoLine compOrderLine, PoLine poLineFromStorage, RequestContext requestContext) { + if (isReleaseEncumbrances(compOrderLine, poLineFromStorage)) { + logger.info("updateEncumbranceStatus:: Encumbrances releasing for poLineId={} where paymentStatus={}", compOrderLine.getId(), compOrderLine.getPaymentStatus()); + return encumbranceService.getPoLineUnreleasedEncumbrances(compOrderLine, requestContext) + .compose(transactionList -> encumbranceService.releaseEncumbrances(transactionList, requestContext)); + } else if (isUnreleasedEncumbrances(compOrderLine, poLineFromStorage)) { + logger.info("updateEncumbranceStatus:: Encumbrances unreleasing for poLineId={} where paymentStatus={}", compOrderLine.getId(), compOrderLine.getPaymentStatus()); + return encumbranceService.getPoLineReleasedEncumbrances(compOrderLine, requestContext) + .compose(transactionList -> encumbranceService.unreleaseEncumbrances(transactionList, requestContext)); + } + return Future.succeededFuture(); } private boolean isReleaseEncumbrances(CompositePoLine compOrderLine, PoLine poLine) { @@ -359,8 +342,7 @@ public Future updateOrderLine(CompositePoLine compOrderLine, JsonObject li .compose(poLine -> purchaseOrderLineService.updateOrderLineSummary(compOrderLine.getId(), poLine, requestContext)) .onSuccess(json -> promise.complete()) .onFailure(throwable -> { - String message = String.format("PO Line with '%s' id partially updated but there are issues processing some PO Line sub-objects", compOrderLine.getId()); - logger.error(message); + logger.error("PoLine with id - '{}' partially updated but there are issues processing some PoLine sub-objects", compOrderLine.getId()); promise.fail(throwable); }); return promise.future(); @@ -386,9 +368,6 @@ public void updateEstimatedPrice(CompositePoLine compPoLine) { } - - - /** * Retrieves PO line from storage by PO line id as JsonObject and validates order id match. */ @@ -413,25 +392,24 @@ private void validateOrderId(String orderId, JsonObject line) { } } - private Future createPoLineSummary(CompositePoLine compPOL, JsonObject jsonLine, RequestContext requestContext) { - RequestEntry rqEntry = new RequestEntry(resourcesPath(PO_LINES_STORAGE)); - var poLine = jsonLine.mapTo(PoLine.class); - return restClient.post(rqEntry, poLine, PoLine.class, requestContext) - .map(createdLine -> compPOL.withId(createdLine.getId()).withPoLineNumber(createdLine.getPoLineNumber())); + private Future createPoLineSummary(CompositePoLine compPOL, PoLine poLine, RequestContext requestContext) { + var requestEntry = new RequestEntry(resourcesPath(PO_LINES_STORAGE)); + return restClient.post(requestEntry, poLine, PoLine.class, requestContext) + .map(createdLine -> compPOL.withId(createdLine.getId()).withPoLineNumber(createdLine.getPoLineNumber())); } - private Future createReportingCodes(CompositePoLine compPOL, JsonObject line, RequestContext requestContext) { - List> futures = new ArrayList<>(); - - List reportingCodes = compPOL.getReportingCodes(); - if (null != reportingCodes) { - RequestEntry rqEntry = new RequestEntry(resourcesPath(REPORTING_CODES)); - reportingCodes - .forEach(reportingObject -> futures.add(restClient.post(rqEntry, reportingObject, ReportingCode.class, requestContext) - .map(ReportingCode::getId))); + private Future createReportingCodes(CompositePoLine compPOL, PoLine poLine, RequestContext requestContext) { + var reportingCodes = compPOL.getReportingCodes(); + if (isEmpty(reportingCodes)) { + return Future.succeededFuture(); } - return GenericCompositeFuture.join(new ArrayList<>(futures)) - .map(reportingIds -> line.put(REPORTING_CODES, reportingIds.list())) + + var requestEntry = new RequestEntry(resourcesPath(REPORTING_CODES)); + var futures = reportingCodes.stream() + .map(reportingObject -> restClient.post(requestEntry, reportingObject, ReportingCode.class, requestContext).map(ReportingCode::getId)) + .toList(); + return GenericCompositeFuture.join(futures) + .map(reportingIds -> poLine.withReportingCodes(reportingIds.list())) .recover(t -> { logger.error("Failed to create reporting codes", t); throw new HttpException(500, "Failed to create reporting codes", t); @@ -439,17 +417,18 @@ private Future createReportingCodes(CompositePoLine compPOL, JsonObject li .mapEmpty(); } - private Future createAlerts(CompositePoLine compPOL, JsonObject line, RequestContext requestContext) { - List> futures = new ArrayList<>(); - - List alerts = compPOL.getAlerts(); - if (null != alerts) { - RequestEntry rqEntry = new RequestEntry(resourcesPath(ALERTS)); - alerts.forEach(alertObject -> futures.add(restClient.post(rqEntry, alertObject, Alert.class, requestContext).map(Alert::getId))); + private Future createAlerts(CompositePoLine compPOL, PoLine poLine, RequestContext requestContext) { + var alerts = compPOL.getAlerts(); + if (isEmpty(alerts)) { + return Future.succeededFuture(); } - return GenericCompositeFuture.join(new ArrayList<>(futures)) - .map(ids -> line.put(ALERTS, ids.list())) + var requestEntry = new RequestEntry(resourcesPath(ALERTS)); + var futures = alerts.stream() + .map(alertObject -> restClient.post(requestEntry, alertObject, Alert.class, requestContext).map(Alert::getId)) + .toList(); + return GenericCompositeFuture.join(futures) + .map(ids -> poLine.withAlerts(ids.list())) .recover(t -> { logger.error("Failed to create alerts", t); throw new HttpException(500, "Failed to create alerts", t); @@ -459,35 +438,32 @@ private Future createAlerts(CompositePoLine compPOL, JsonObject line, Requ public Future updatePoLines(CompositePurchaseOrder poFromStorage, CompositePurchaseOrder compPO, RequestContext requestContext) { logger.debug("updatePoLines start"); - if (isPoLinesUpdateRequired(poFromStorage, compPO)) { - List existingPoLines = HelperUtils.convertToPoLines(poFromStorage.getCompositePoLines()); - if (isNotEmpty(compPO.getCompositePoLines())) { - // New PO Line(s) can be added only to Pending order - if (poFromStorage.getWorkflowStatus() != PENDING && hasNewPoLines(compPO, existingPoLines)) { - throw new HttpException(422, poFromStorage.getWorkflowStatus() == OPEN ? ErrorCodes.ORDER_OPEN : ErrorCodes.ORDER_CLOSED); - } - validatePOLineProtectedFieldsChangedInPO(poFromStorage, compPO, existingPoLines); - return handlePoLines(compPO, existingPoLines, requestContext); - } else { - return updatePoLinesNumber(compPO, existingPoLines, requestContext); - } + if (!isPoLinesUpdateRequired(poFromStorage, compPO)) { + return Future.succeededFuture(); } - return Future.succeededFuture(); + var existingPoLines = HelperUtils.convertToPoLines(poFromStorage.getCompositePoLines()); + if (isEmpty(compPO.getCompositePoLines())) { + return updatePoLinesNumber(compPO, existingPoLines, requestContext); + } + // New PO Line(s) can be added only to Pending order + if (poFromStorage.getWorkflowStatus() != PENDING && getNewPoLines(compPO, existingPoLines).findAny().isPresent()) { + throw new HttpException(422, poFromStorage.getWorkflowStatus() == OPEN ? ErrorCodes.ORDER_OPEN : ErrorCodes.ORDER_CLOSED); + } + validatePoLineProtectedFieldsChangedOrder(compPO, existingPoLines); + return handlePoLines(compPO, existingPoLines, requestContext); } - private void validatePOLineProtectedFieldsChangedInPO(CompositePurchaseOrder poFromStorage, CompositePurchaseOrder compPO, - List existingPoLines) { - if (poFromStorage.getWorkflowStatus() != PENDING) { - compPO.getCompositePoLines() - .forEach(poLine -> verifyProtectedFieldsChanged(POLineProtectedFieldsUtil.getFieldNames(poLine.getOrderFormat().value()), - findCorrespondingCompositePoLine(poLine, existingPoLines), JsonObject.mapFrom(poLine))); - } + private void validatePoLineProtectedFieldsChangedOrder(CompositePurchaseOrder compPO, List existingPoLines) { + compPO.getCompositePoLines().forEach(poLine -> { + var fields = POLineProtectedFieldsUtil.getFieldNames(poLine.getOrderFormat().value()); + var correspondingLine = findCorrespondingCompositePoLine(poLine, existingPoLines); + verifyProtectedFieldsChanged(fields, correspondingLine, JsonObject.mapFrom(poLine)); + }); } private JsonObject findCorrespondingCompositePoLine(CompositePoLine poLine, List poLinesFromStorage) { return poLinesFromStorage.stream() - .filter(line -> line.getId() - .equals(poLine.getId())) + .filter(line -> line.getId().equals(poLine.getId())) .findFirst() .map(JsonObject::mapFrom) .orElse(null); @@ -498,15 +474,10 @@ private boolean isPoLinesUpdateRequired(CompositePurchaseOrder poFromStorage, Co } private Future updatePoLinesNumber(CompositePurchaseOrder compOrder, List poLinesFromStorage, RequestContext requestContext) { - List> futures = poLinesFromStorage - .stream() - .map(lineFromStorage -> { - lineFromStorage.setPoLineNumber(buildNewPoLineNumber(lineFromStorage, compOrder.getPoNumber())); - return purchaseOrderLineService.saveOrderLine(lineFromStorage, requestContext); - }) - .toList(); - - return GenericCompositeFuture.join(new ArrayList<>(futures)) + return GenericCompositeFuture.join(poLinesFromStorage.stream() + .map(lineFromStorage -> lineFromStorage.withPoLineNumber(buildNewPoLineNumber(lineFromStorage, compOrder.getPoNumber()))) + .map(lineFromStorage -> purchaseOrderLineService.saveOrderLine(lineFromStorage, requestContext)) + .toList()) .mapEmpty(); } @@ -516,18 +487,15 @@ private Future handlePoLines(CompositePurchaseOrder compOrder, List futures.add(orderInvoiceRelationService.checkOrderInvoiceRelationship(compOrder.getId(), requestContext) - .compose(v -> encumbranceService.deletePoLineEncumbrances(poLine, requestContext) - .compose(ok -> purchaseOrderLineService.deletePoLine(poLine, requestContext))))); - + poLinesFromStorage.forEach(poLine -> futures.add( + orderInvoiceRelationService.checkOrderInvoiceRelationship(compOrder.getId(), requestContext) + .compose(v -> encumbranceService.deletePoLineEncumbrances(poLine, requestContext)) + .compose(v -> purchaseOrderLineService.deletePoLine(poLine, requestContext)))); } - return GenericCompositeFuture.join(futures) - .mapEmpty(); + return GenericCompositeFuture.join(futures).mapEmpty(); } - private List> processPoLinesUpdate(CompositePurchaseOrder compOrder, List poLinesFromStorage, - RequestContext requestContext) { + private List> processPoLinesUpdate(CompositePurchaseOrder compOrder, List poLinesFromStorage, RequestContext requestContext) { List> futures = new ArrayList<>(); Iterator iterator = poLinesFromStorage.iterator(); while (iterator.hasNext()) { @@ -547,25 +515,15 @@ private List> processPoLinesUpdate(CompositePurchaseOrder compOrder, L return futures; } - private List> processPoLinesCreation(CompositePurchaseOrder compOrder, List poLinesFromStorage, - RequestContext requestContext) { + private List> processPoLinesCreation(CompositePurchaseOrder compOrder, List poLinesFromStorage, RequestContext requestContext) { return getNewPoLines(compOrder, poLinesFromStorage) .map(compPOL -> createPoLineWithOrder(compPOL, compOrder, requestContext)) .toList(); } - private boolean hasNewPoLines(CompositePurchaseOrder compPO, List poLinesFromStorage) { - return getNewPoLines(compPO, poLinesFromStorage).findAny().isPresent(); - } - private Stream getNewPoLines(CompositePurchaseOrder compPO, List poLinesFromStorage) { - List lineIdsInStorage = poLinesFromStorage - .stream() - .map(PoLine::getId) - .toList(); - - return compPO.getCompositePoLines() - .stream() + var lineIdsInStorage = poLinesFromStorage.stream().map(PoLine::getId).toList(); + return compPO.getCompositePoLines().stream() .filter(poLine -> !lineIdsInStorage.contains(poLine.getId())); } @@ -574,22 +532,20 @@ private boolean isPoNumberChanged(CompositePurchaseOrder poFromStorage, Composit } private void checkLocationCanBeModified(CompositePoLine poLine, PoLine lineFromStorage, CompositePurchaseOrder order) { - boolean isOrderOpenAndNoNeedToManualAddPiecesForCreationAndLocationModified = order.getWorkflowStatus() == OPEN + if (order.getWorkflowStatus() == OPEN && !poLine.getSource().equals(CompositePoLine.Source.EBSCONET) && Boolean.FALSE.equals(poLine.getCheckinItems()) - && !isEqualCollection(poLine.getLocations(), lineFromStorage.getLocations()); - - if (isOrderOpenAndNoNeedToManualAddPiecesForCreationAndLocationModified) { + && !isEqualCollection(poLine.getLocations(), lineFromStorage.getLocations())) { throw new HttpException(400, LOCATION_CAN_NOT_BE_MODIFIER_AFTER_OPEN); } } private CompositePurchaseOrder validateOrderState(CompositePurchaseOrder po) { - CompositePurchaseOrder.WorkflowStatus poStatus = po.getWorkflowStatus(); - if (poStatus != PENDING) { - throw new HttpException(422, poStatus == OPEN ? ErrorCodes.ORDER_OPEN : ErrorCodes.ORDER_CLOSED); + var poStatus = po.getWorkflowStatus(); + if (poStatus == PENDING) { + return po; } - return po; + throw new HttpException(422, poStatus == OPEN ? ErrorCodes.ORDER_OPEN : ErrorCodes.ORDER_CLOSED); } /** @@ -598,36 +554,31 @@ private CompositePurchaseOrder validateOrderState(CompositePurchaseOrder po) { * @param tenantConfiguration Tenant configuration * @return completable future which might be completed with {@code true} if line is valid, {@code false} if not valid or an exception if processing fails */ - private Future> validateNewPoLine(CompositePoLine compPOL, JsonObject tenantConfiguration, - RequestContext requestContext) { + private Future> validateNewPoLine(CompositePoLine compPOL, JsonObject tenantConfiguration, RequestContext requestContext) { logger.debug("Validating if PO Line is valid..."); List errors = new ArrayList<>(); if (compPOL.getPurchaseOrderId() == null) { errors.add(ErrorCodes.MISSING_ORDER_ID_IN_POL.toError()); } - // If static validation has failed, no need to call other services - if (CollectionUtils.isNotEmpty(errors)) { + if (isNotEmpty(errors)) { return Future.succeededFuture(errors); } - return compositePoLineValidationService.validatePoLine(compPOL, requestContext) .compose(poLineErrors -> { - if (CollectionUtils.isEmpty(poLineErrors)) { - return validatePoLineLimit(compPOL, tenantConfiguration, requestContext) - .compose(aErrors -> { - if (CollectionUtils.isEmpty(aErrors)) { - return purchaseOrderLineService.validateAndNormalizeISBN(Collections.singletonList(compPOL), requestContext) - .map(v -> errors); - } else { - errors.addAll(aErrors); - return Future.succeededFuture(errors); - } - }); - } else { + if (isNotEmpty(poLineErrors)) { errors.addAll(poLineErrors); return Future.succeededFuture(errors); } + return validatePoLineLimit(compPOL, tenantConfiguration, requestContext) + .compose(aErrors -> { + if (isNotEmpty(aErrors)) { + errors.addAll(aErrors); + return Future.succeededFuture(errors); + } + return purchaseOrderLineService.validateAndNormalizeISBN(Collections.singletonList(compPOL), requestContext) + .map(v -> errors); + }); }); } @@ -652,10 +603,9 @@ private Future getCompositePurchaseOrder(String purchase .onFailure(cause -> { // The case when specified order does not exist if (cause instanceof HttpException httpException && httpException.getCode() == Response.Status.NOT_FOUND.getStatusCode()) { - promise.fail(new HttpException(422, ErrorCodes.ORDER_NOT_FOUND)); - } else { - promise.fail(cause); + cause = new HttpException(422, ErrorCodes.ORDER_NOT_FOUND); } + promise.fail(cause); }); return promise.future(); @@ -672,36 +622,31 @@ private Future generateLineNumber(CompositePurchaseOrder compOrder, Requ private Future populateCompositeLine(PoLine poline, RequestContext requestContext) { return purchaseOrderLineService.operateOnPoLine(HttpMethod.GET, poline, requestContext) - .compose(compPol -> getLineWithInstanceId(compPol, requestContext)); } + .compose(compPol -> getLineWithInstanceId(compPol, requestContext)); + } private Future getLineWithInstanceId(CompositePoLine line, RequestContext requestContext) { - if (!Boolean.TRUE.equals(line.getIsPackage())) { - return titlesService.getTitles(1, 0, QUERY_BY_PO_LINE_ID + line.getId(), requestContext) - .map(titleCollection -> { - List titles = titleCollection.getTitles(); - if (!titles.isEmpty()) { - line.setInstanceId(titles.get(0).getInstanceId()); - } - return line; - }); - } else { + if (Boolean.TRUE.equals(line.getIsPackage())) { return Future.succeededFuture(line); } + return titlesService.getTitles(1, 0, QUERY_BY_PO_LINE_ID + line.getId(), requestContext) + .map(titleCollection -> { + var titles = titleCollection.getTitles(); + if (!titles.isEmpty()) { + line.setInstanceId(titles.get(0).getInstanceId()); + } + return line; + }); } - private CompositePurchaseOrder addLineToCompOrder(CompositePurchaseOrder compOrder, JsonObject lineFromStorage) { - PoLine poLine = lineFromStorage.mapTo(PoLine.class); - poLine.setAlerts(null); - poLine.setReportingCodes(null); - CompositePoLine compPoLine = JsonObject.mapFrom(poLine).mapTo(CompositePoLine.class); + private CompositePurchaseOrder addLineToCompOrder(CompositePurchaseOrder compOrder, PoLine poLine) { + var compPoLine = JsonObject.mapFrom(poLine.withAlerts(null).withReportingCodes(null)).mapTo(CompositePoLine.class); compOrder.getCompositePoLines().add(compPoLine); return compOrder; } private Future<Void> processPoLineEncumbrances(CompositePurchaseOrder compOrder, CompositePoLine compositePoLine, - JsonObject lineFromStorage, RequestContext requestContext) { - PoLine storagePoLine = lineFromStorage.mapTo(PoLine.class); - + PoLine storagePoLine, RequestContext requestContext) { List<String> storageFundIds = storagePoLine.getFundDistribution().stream() .map(FundDistribution::getFundId) .toList(); @@ -709,10 +654,10 @@ private Future<Void> processPoLineEncumbrances(CompositePurchaseOrder compOrder, compositePoLine.getFundDistribution().stream() .filter(fundDistribution -> storageFundIds.contains(fundDistribution.getFundId()) && fundDistribution.getEncumbrance() == null) .forEach(fundDistribution -> storagePoLine.getFundDistribution().stream() - .filter(storageFundDistribution -> storageFundDistribution.getFundId().equals(fundDistribution.getFundId())) - .filter(storageFundDistribution -> Objects.equals(storageFundDistribution.getExpenseClassId(), fundDistribution.getExpenseClassId())) - .findFirst() - .ifPresent(storageFundDistribution -> fundDistribution.setEncumbrance(storageFundDistribution.getEncumbrance()))); + .filter(storageFundDistribution -> storageFundDistribution.getFundId().equals(fundDistribution.getFundId())) + .filter(storageFundDistribution -> Objects.equals(storageFundDistribution.getExpenseClassId(), fundDistribution.getExpenseClassId())) + .findFirst() + .ifPresent(storageFundDistribution -> fundDistribution.setEncumbrance(storageFundDistribution.getEncumbrance()))); if (isEncumbranceUpdateNeeded(compOrder, compositePoLine, storagePoLine)) { OrderWorkflowType workflowType = compOrder.getWorkflowStatus() == PENDING ? @@ -724,36 +669,19 @@ private Future<Void> processPoLineEncumbrances(CompositePurchaseOrder compOrder, return Future.succeededFuture(); } - private Future<Void> updateInventoryItemStatus(CompositePoLine compOrderLine, JsonObject lineFromStorage, RequestContext requestContext) { - PoLine poLineFromStorage = lineFromStorage.mapTo(PoLine.class); - if (isStatusChanged(compOrderLine, poLineFromStorage) && isCurrentStatusCanceled(compOrderLine)) { - return purchaseOrderLineService.getPoLinesByOrderId(compOrderLine.getPurchaseOrderId(), requestContext) - .compose(poLines -> { - List<PoLine> notCanceledPoLines = poLines.stream().filter(Predicate.not(this::isDbPoLineStatusCancelled)).toList(); - if (CollectionUtils.isEmpty(notCanceledPoLines)) { - logger.info("updateInventoryItemStatus:: not canceled po lines not found, returning..."); - return Future.succeededFuture(null); - } - return itemStatusSyncService.updateInventoryItemStatus(compOrderLine.getId(), compOrderLine.getLocations(), - ItemStatus.ORDER_CLOSED, requestContext); - }); + private Future<Void> updateInventoryItemStatus(CompositePoLine compOrderLine, PoLine lineFromStorage, RequestContext requestContext) { + if (!isStatusChanged(compOrderLine, lineFromStorage) || !isPoLineStatusCanceled(compOrderLine)) { + return Future.succeededFuture(); } - return Future.succeededFuture(null); - } - - private boolean isStatusChanged(CompositePoLine compOrderLine, PoLine lineFromStorage) { - return !StringUtils.equals(lineFromStorage.getReceiptStatus().value(), compOrderLine.getReceiptStatus().value()) || - !StringUtils.equals(lineFromStorage.getPaymentStatus().value(), compOrderLine.getPaymentStatus().value()); - } - - private boolean isDbPoLineStatusCancelled(PoLine poLine) { - return PoLine.PaymentStatus.CANCELLED.equals(poLine.getPaymentStatus()) || - PoLine.ReceiptStatus.CANCELLED.equals(poLine.getReceiptStatus()); - } - - private boolean isCurrentStatusCanceled(CompositePoLine compOrderLine) { - return CompositePoLine.ReceiptStatus.CANCELLED.equals(compOrderLine.getReceiptStatus()) || - CompositePoLine.PaymentStatus.CANCELLED.equals(compOrderLine.getPaymentStatus()); + return purchaseOrderLineService.getPoLinesByOrderId(compOrderLine.getPurchaseOrderId(), requestContext) + .compose(poLines -> { + if (areAllPoLinesCanceled(poLines)) { + logger.info("updateInventoryItemStatus:: All PoLines are canceled, returning..."); + return Future.succeededFuture(); + } + return itemStatusSyncService.updateInventoryItemStatus(compOrderLine.getId(), compOrderLine.getLocations(), + ItemStatus.ORDER_CLOSED, requestContext); + }); } private boolean isEncumbranceUpdateNeeded(CompositePurchaseOrder compOrder, CompositePoLine compositePoLine, PoLine storagePoLine) { @@ -802,24 +730,12 @@ private Future<Void> validateAccessProviders(CompositePoLine compOrderLine, Requ } - private void validatePOLineProtectedFieldsChanged(CompositePoLine compOrderLine, JsonObject lineFromStorage, CompositePurchaseOrder purchaseOrder) { + private void validatePOLineProtectedFieldsChanged(CompositePoLine compOrderLine, PoLine poLineFromStorage, CompositePurchaseOrder purchaseOrder) { if (purchaseOrder.getWorkflowStatus() != PENDING) { - verifyProtectedFieldsChanged(POLineProtectedFieldsUtil.getFieldNames(compOrderLine.getOrderFormat().value()), JsonObject.mapFrom(lineFromStorage.mapTo(PoLine.class)), JsonObject.mapFrom(compOrderLine)); - } - } - - private void updateOrderStatus(CompositePoLine compOrderLine, JsonObject lineFromStorage, RequestContext requestContext) { - PoLine poLine = lineFromStorage.mapTo(PoLine.class); - // See MODORDERS-218 - if (isStatusChanged(compOrderLine, poLine)) { - HelperUtils.sendEvent(MessageAddress.RECEIVE_ORDER_STATUS_UPDATE, createUpdateOrderMessage(compOrderLine), requestContext); + verifyProtectedFieldsChanged(POLineProtectedFieldsUtil.getFieldNames(compOrderLine.getOrderFormat().value()), JsonObject.mapFrom(poLineFromStorage), JsonObject.mapFrom(compOrderLine)); } } - private JsonObject createUpdateOrderMessage(CompositePoLine compOrderLine) { - return new JsonObject().put(EVENT_PAYLOAD, new JsonArray().add(new JsonObject().put(ORDER_ID, compOrderLine.getPurchaseOrderId()))); - } - private Physical.CreateInventory getPhysicalInventoryDefault(String tenantDefault) { return StringUtils.isEmpty(tenantDefault) ? Physical.CreateInventory.INSTANCE_HOLDING_ITEM @@ -863,7 +779,7 @@ private void updateCreateInventory(CompositePoLine compPOL, JsonObject jsonConfi if (compPOL.getEresource() == null) { compPOL.setEresource(new Eresource()); } - if(isEresourceInventoryNotPresent(compPOL)) { + if (isEresourceInventoryNotPresent(compPOL)) { compPOL.getEresource().setCreateInventory(eresourceDefaultValue); } } diff --git a/src/main/java/org/folio/models/PoLineInvoiceLineHolder.java b/src/main/java/org/folio/models/PoLineInvoiceLineHolder.java index 6055bd2ea..e67921c4c 100644 --- a/src/main/java/org/folio/models/PoLineInvoiceLineHolder.java +++ b/src/main/java/org/folio/models/PoLineInvoiceLineHolder.java @@ -7,8 +7,6 @@ import org.folio.rest.jaxrs.model.CompositePoLine; import org.folio.rest.jaxrs.model.PoLine; -import io.vertx.core.json.JsonObject; - public class PoLineInvoiceLineHolder { private CompositePoLine poLineFromRequest; @@ -16,9 +14,9 @@ public class PoLineInvoiceLineHolder { private List<InvoiceLine> invoiceLines; private List<InvoiceLine> openOrReviewedInvoiceLines; - public PoLineInvoiceLineHolder(CompositePoLine poLineFromRequest, JsonObject poLineFromStorage) { + public PoLineInvoiceLineHolder(CompositePoLine poLineFromRequest, PoLine poLineFromStorage) { this.poLineFromRequest = poLineFromRequest; - this.poLineFromStorage = poLineFromStorage.mapTo(PoLine.class); + this.poLineFromStorage = poLineFromStorage; this.invoiceLines = new ArrayList<>(); this.openOrReviewedInvoiceLines = new ArrayList<>(); } diff --git a/src/main/java/org/folio/service/invoice/PoLineInvoiceLineHolderBuilder.java b/src/main/java/org/folio/service/invoice/PoLineInvoiceLineHolderBuilder.java index 5e1e066ee..796002741 100644 --- a/src/main/java/org/folio/service/invoice/PoLineInvoiceLineHolderBuilder.java +++ b/src/main/java/org/folio/service/invoice/PoLineInvoiceLineHolderBuilder.java @@ -11,7 +11,6 @@ import org.folio.rest.jaxrs.model.PoLine; import io.vertx.core.Future; -import io.vertx.core.json.JsonObject; public class PoLineInvoiceLineHolderBuilder { private static final List<InvoiceLine.InvoiceLineStatus> EDITABLE_STATUSES = List.of(InvoiceLine.InvoiceLineStatus.OPEN, InvoiceLine.InvoiceLineStatus.REVIEWED); @@ -22,7 +21,7 @@ public PoLineInvoiceLineHolderBuilder(InvoiceLineService invoiceLineService) { } public Future<PoLineInvoiceLineHolder> buildHolder(CompositePoLine compOrderLine, PoLine poLineFromStorage, RequestContext requestContext) { - PoLineInvoiceLineHolder holder = new PoLineInvoiceLineHolder(compOrderLine, JsonObject.mapFrom(poLineFromStorage)); + var holder = new PoLineInvoiceLineHolder(compOrderLine, poLineFromStorage); return invoiceLineService.getInvoiceLinesByOrderLineId(compOrderLine.getId(), requestContext) .onSuccess(holder::withInvoiceLines) .compose(aResult -> CollectionUtils.isEmpty(holder.getInvoiceLines()) ? Future.succeededFuture(holder) : diff --git a/src/main/java/org/folio/service/orders/utils/StatusUtils.java b/src/main/java/org/folio/service/orders/utils/StatusUtils.java new file mode 100644 index 000000000..ed7fffa23 --- /dev/null +++ b/src/main/java/org/folio/service/orders/utils/StatusUtils.java @@ -0,0 +1,53 @@ +package org.folio.service.orders.utils; + +import io.vertx.core.Future; +import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; +import org.apache.commons.lang3.StringUtils; +import org.folio.orders.events.handlers.MessageAddress; +import org.folio.orders.utils.HelperUtils; +import org.folio.rest.core.models.RequestContext; +import org.folio.rest.jaxrs.model.CompositePoLine; +import org.folio.rest.jaxrs.model.PoLine; + +import java.util.List; + +import static org.folio.helper.BaseHelper.EVENT_PAYLOAD; +import static org.folio.helper.BaseHelper.ORDER_ID; + +public class StatusUtils { + + public static Future<Void> updateOrderStatusIfNeeded(CompositePoLine compOrderLine, JsonObject lineFromStorage, RequestContext requestContext) { + // See MODORDERS-218 + if (isStatusChanged(compOrderLine, lineFromStorage.mapTo(PoLine.class))) { + var updateOrderMessage = JsonObject.of(EVENT_PAYLOAD, JsonArray.of(JsonObject.of(ORDER_ID, compOrderLine.getPurchaseOrderId()))); + HelperUtils.sendEvent(MessageAddress.RECEIVE_ORDER_STATUS_UPDATE, updateOrderMessage, requestContext); + } + return Future.succeededFuture(); + } + + public static boolean isStatusChanged(CompositePoLine compOrderLine, PoLine lineFromStorage) { + return !StringUtils.equals(lineFromStorage.getReceiptStatus().value(), compOrderLine.getReceiptStatus().value()) || + !StringUtils.equals(lineFromStorage.getPaymentStatus().value(), compOrderLine.getPaymentStatus().value()); + } + + public static boolean shouldUpdateOrderStatus(CompositePoLine compOrderLine, PoLine lineFromStorage) { + return !StringUtils.equals(lineFromStorage.getReceiptStatus().value(), compOrderLine.getReceiptStatus().value()) || + !StringUtils.equals(lineFromStorage.getPaymentStatus().value(), compOrderLine.getPaymentStatus().value()); + } + + public static boolean areAllPoLinesCanceled(List<PoLine> poLines) { + return poLines.stream().allMatch(StatusUtils::isPoLineStatusCanceled); + } + + private static boolean isPoLineStatusCanceled(PoLine poLine) { + return PoLine.PaymentStatus.CANCELLED.equals(poLine.getPaymentStatus()) || + PoLine.ReceiptStatus.CANCELLED.equals(poLine.getReceiptStatus()); + } + + public static boolean isPoLineStatusCanceled(CompositePoLine compOrderLine) { + return CompositePoLine.ReceiptStatus.CANCELLED.equals(compOrderLine.getReceiptStatus()) || + CompositePoLine.PaymentStatus.CANCELLED.equals(compOrderLine.getPaymentStatus()); + } + +} From f3e30da44d4b0f8c1d512f14ab2fcaaccecc4ad6 Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Thu, 19 Sep 2024 18:49:17 +0400 Subject: [PATCH 02/11] [MODORDERS-1174] Minor refactoring --- .../folio/helper/PurchaseOrderLineHelper.java | 74 +++++++++---------- .../folio/models/PoLineInvoiceLineHolder.java | 5 +- .../service/orders/utils/StatusUtils.java | 6 +- 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index 7e68a53c5..040508204 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -19,7 +19,7 @@ import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.OPEN; import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.PENDING; import static org.folio.service.orders.utils.StatusUtils.areAllPoLinesCanceled; -import static org.folio.service.orders.utils.StatusUtils.isPoLineStatusCanceled; +import static org.folio.service.orders.utils.StatusUtils.isCompositePoLineStatusCanceled; import static org.folio.service.orders.utils.StatusUtils.isStatusChanged; import static org.folio.service.orders.utils.StatusUtils.updateOrderStatusIfNeeded; @@ -271,32 +271,30 @@ public Future<Void> deleteLine(String lineId, RequestContext requestContext) { */ public Future<Void> updateOrderLine(CompositePoLine compOrderLine, RequestContext requestContext) { return getPoLineByIdAndValidate(compOrderLine.getPurchaseOrderId(), compOrderLine.getId(), requestContext) - .compose(lineFromStorage -> { - var poLineFromStorage = lineFromStorage.mapTo(PoLine.class); - return getCompositePurchaseOrder(compOrderLine.getPurchaseOrderId(), requestContext) - .map(compOrder -> addLineToCompOrder(compOrder, poLineFromStorage)) - .map(compOrder -> { - validatePOLineProtectedFieldsChanged(compOrderLine, poLineFromStorage, compOrder); - PoLineCommonUtil.updateLocationsQuantity(compOrderLine.getLocations()); - updateEstimatedPrice(compOrderLine); - checkLocationCanBeModified(compOrderLine, poLineFromStorage, compOrder); - return compOrder; - }) - .compose(compOrder -> protectionService.isOperationRestricted(compOrder.getAcqUnitIds(), UPDATE, requestContext) - .compose(v -> purchaseOrderLineService.validateAndNormalizeISBNAndProductType(Collections.singletonList(compOrderLine), requestContext)) - .compose(v -> validateAccessProviders(compOrderLine, requestContext)) - .compose(v -> expenseClassValidationService.validateExpenseClassesForOpenedOrder(compOrder, Collections.singletonList(compOrderLine), requestContext)) - .compose(v -> processPoLineEncumbrances(compOrder, compOrderLine, poLineFromStorage, requestContext))) - .map(v -> compOrderLine.withPoLineNumber(poLineFromStorage.getPoLineNumber())) // PoLine number must not be modified during PoLine update, set original value - .map(v -> new PoLineInvoiceLineHolder(compOrderLine, poLineFromStorage)) - .compose(poLineInvoiceLineHolder -> polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext) - .compose(v -> createShadowInstanceIfNeeded(compOrderLine, requestContext)) - .compose(v -> updateOrderLine(compOrderLine, lineFromStorage, requestContext)) - .compose(v -> updateEncumbranceStatus(compOrderLine, poLineFromStorage, requestContext)) - .compose(v -> polInvoiceLineRelationService.updateInvoiceLineReference(poLineInvoiceLineHolder, requestContext)) - .compose(v -> updateInventoryItemStatus(compOrderLine, poLineFromStorage, requestContext)) - .compose(v -> updateOrderStatusIfNeeded(compOrderLine, lineFromStorage, requestContext))); - }); + .map(lineFromStorage -> lineFromStorage.mapTo(PoLine.class)) + .compose(poLineFromStorage -> getCompositePurchaseOrder(compOrderLine.getPurchaseOrderId(), requestContext) + .map(compOrder -> addLineToCompOrder(compOrder, poLineFromStorage)) + .map(compOrder -> { + validatePOLineProtectedFieldsChanged(compOrderLine, poLineFromStorage, compOrder); + PoLineCommonUtil.updateLocationsQuantity(compOrderLine.getLocations()); + updateEstimatedPrice(compOrderLine); + checkLocationCanBeModified(compOrderLine, poLineFromStorage, compOrder); + return compOrder; + }) + .compose(compOrder -> protectionService.isOperationRestricted(compOrder.getAcqUnitIds(), UPDATE, requestContext) + .compose(v -> purchaseOrderLineService.validateAndNormalizeISBNAndProductType(Collections.singletonList(compOrderLine), requestContext)) + .compose(v -> validateAccessProviders(compOrderLine, requestContext)) + .compose(v -> expenseClassValidationService.validateExpenseClassesForOpenedOrder(compOrder, Collections.singletonList(compOrderLine), requestContext)) + .compose(v -> processPoLineEncumbrances(compOrder, compOrderLine, poLineFromStorage, requestContext))) + .map(v -> compOrderLine.withPoLineNumber(poLineFromStorage.getPoLineNumber())) // PoLine number must not be modified during PoLine update, set original value + .map(v -> new PoLineInvoiceLineHolder(compOrderLine, poLineFromStorage)) + .compose(poLineInvoiceLineHolder -> polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext) + .compose(v -> createShadowInstanceIfNeeded(compOrderLine, requestContext)) + .compose(v -> updateOrderLine(compOrderLine, JsonObject.mapFrom(poLineFromStorage), requestContext)) + .compose(v -> updateEncumbranceStatus(compOrderLine, poLineFromStorage, requestContext)) + .compose(v -> polInvoiceLineRelationService.updateInvoiceLineReference(poLineInvoiceLineHolder, requestContext)) + .compose(v -> updateInventoryItemStatus(compOrderLine, poLineFromStorage, requestContext)) + .compose(v -> updateOrderStatusIfNeeded(compOrderLine, poLineFromStorage, requestContext)))); } private Future<Void> updateEncumbranceStatus(CompositePoLine compOrderLine, PoLine poLineFromStorage, RequestContext requestContext) { @@ -373,21 +371,20 @@ public void updateEstimatedPrice(CompositePoLine compPoLine) { */ private Future<JsonObject> getPoLineByIdAndValidate(String orderId, String lineId, RequestContext requestContext) { return purchaseOrderLineService.getOrderLineById(lineId, requestContext) - .map(JsonObject::mapFrom) - .map(line -> { + .map(poLine -> { logger.debug("Validating if the retrieved PO line corresponds to PO"); - validateOrderId(orderId, line); - return line; + validateOrderId(orderId, poLine); + return JsonObject.mapFrom(poLine); }); } /** * Validates if the retrieved PO line corresponds to PO (orderId). In case the PO line does not correspond to order id the exception is thrown * @param orderId order identifier - * @param line PO line retrieved from storage + * @param poLine PO line retrieved from storage */ - private void validateOrderId(String orderId, JsonObject line) { - if (!StringUtils.equals(orderId, line.getString(PURCHASE_ORDER_ID))) { + private void validateOrderId(String orderId, PoLine poLine) { + if (!StringUtils.equals(orderId, poLine.getPurchaseOrderId())) { throw new HttpException(422, ErrorCodes.INCORRECT_ORDER_ID_IN_POL); } } @@ -670,7 +667,7 @@ private Future<Void> processPoLineEncumbrances(CompositePurchaseOrder compOrder, } private Future<Void> updateInventoryItemStatus(CompositePoLine compOrderLine, PoLine lineFromStorage, RequestContext requestContext) { - if (!isStatusChanged(compOrderLine, lineFromStorage) || !isPoLineStatusCanceled(compOrderLine)) { + if (!isStatusChanged(compOrderLine, lineFromStorage) || !isCompositePoLineStatusCanceled(compOrderLine)) { return Future.succeededFuture(); } return purchaseOrderLineService.getPoLinesByOrderId(compOrderLine.getPurchaseOrderId(), requestContext) @@ -720,8 +717,7 @@ static boolean hasAlteredExchangeRate(Cost oldCost, Cost newCost) { private Future<Void> validateAccessProviders(CompositePoLine compOrderLine, RequestContext requestContext) { return organizationService.validateAccessProviders(Collections.singletonList(compOrderLine), requestContext) .map(errors -> { - if (!errors.getErrors() - .isEmpty()) { + if (!isNotEmpty(errors.getErrors())) { throw new HttpException(422, errors.getErrors().get(0)); } return null; @@ -798,8 +794,8 @@ private void updateCreateInventory(CompositePoLine compPOL, JsonObject jsonConfi private Future<Void> verifyDeleteAllowed(PoLine line, RequestContext requestContext) { return orderInvoiceRelationService.checkOrderPOLineLinkedToInvoiceLine(line, requestContext) - .compose(v -> getCompositePurchaseOrder(line.getPurchaseOrderId(), requestContext) - .compose(order -> protectionService.isOperationRestricted(order.getAcqUnitIds(), DELETE, requestContext))); + .compose(v -> getCompositePurchaseOrder(line.getPurchaseOrderId(), requestContext)) + .compose(order -> protectionService.isOperationRestricted(order.getAcqUnitIds(), DELETE, requestContext)); } private Future<Void> createShadowInstanceIfNeeded(CompositePoLine compositePoLine, RequestContext requestContext) { diff --git a/src/main/java/org/folio/models/PoLineInvoiceLineHolder.java b/src/main/java/org/folio/models/PoLineInvoiceLineHolder.java index e67921c4c..7c001a891 100644 --- a/src/main/java/org/folio/models/PoLineInvoiceLineHolder.java +++ b/src/main/java/org/folio/models/PoLineInvoiceLineHolder.java @@ -9,8 +9,9 @@ public class PoLineInvoiceLineHolder { - private CompositePoLine poLineFromRequest; - private PoLine poLineFromStorage; + + private final CompositePoLine poLineFromRequest; + private final PoLine poLineFromStorage; private List<InvoiceLine> invoiceLines; private List<InvoiceLine> openOrReviewedInvoiceLines; diff --git a/src/main/java/org/folio/service/orders/utils/StatusUtils.java b/src/main/java/org/folio/service/orders/utils/StatusUtils.java index ed7fffa23..dbbec5e8f 100644 --- a/src/main/java/org/folio/service/orders/utils/StatusUtils.java +++ b/src/main/java/org/folio/service/orders/utils/StatusUtils.java @@ -17,9 +17,9 @@ public class StatusUtils { - public static Future<Void> updateOrderStatusIfNeeded(CompositePoLine compOrderLine, JsonObject lineFromStorage, RequestContext requestContext) { + public static Future<Void> updateOrderStatusIfNeeded(CompositePoLine compOrderLine, PoLine poLineFromStorage, RequestContext requestContext) { // See MODORDERS-218 - if (isStatusChanged(compOrderLine, lineFromStorage.mapTo(PoLine.class))) { + if (isStatusChanged(compOrderLine, poLineFromStorage)) { var updateOrderMessage = JsonObject.of(EVENT_PAYLOAD, JsonArray.of(JsonObject.of(ORDER_ID, compOrderLine.getPurchaseOrderId()))); HelperUtils.sendEvent(MessageAddress.RECEIVE_ORDER_STATUS_UPDATE, updateOrderMessage, requestContext); } @@ -45,7 +45,7 @@ private static boolean isPoLineStatusCanceled(PoLine poLine) { PoLine.ReceiptStatus.CANCELLED.equals(poLine.getReceiptStatus()); } - public static boolean isPoLineStatusCanceled(CompositePoLine compOrderLine) { + public static boolean isCompositePoLineStatusCanceled(CompositePoLine compOrderLine) { return CompositePoLine.ReceiptStatus.CANCELLED.equals(compOrderLine.getReceiptStatus()) || CompositePoLine.PaymentStatus.CANCELLED.equals(compOrderLine.getPaymentStatus()); } From d16822e40fa19f123c2ac66ab178335766183086 Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Thu, 19 Sep 2024 19:22:20 +0400 Subject: [PATCH 03/11] [MODORDERS-1174] Prevent incorrect order reopen --- .../folio/helper/PurchaseOrderLineHelper.java | 25 ++++++++++--------- .../service/orders/utils/StatusUtils.java | 19 ++++++++++---- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index 040508204..b95a01560 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -98,7 +98,7 @@ public class PurchaseOrderLineHelper { public static final String ERESOURCE = "eresource"; public static final String PHYSICAL = "physical"; private static final String OTHER = "other"; - private static final String QUERY_BY_PO_LINE_ID = "poLineId=="; + private static final String QUERY_BY_PO_LINE_ID = "poLineId==%s"; private final InventoryItemStatusSyncService itemStatusSyncService; private final InventoryInstanceManager inventoryInstanceManager; @@ -285,16 +285,16 @@ public Future<Void> updateOrderLine(CompositePoLine compOrderLine, RequestContex .compose(v -> purchaseOrderLineService.validateAndNormalizeISBNAndProductType(Collections.singletonList(compOrderLine), requestContext)) .compose(v -> validateAccessProviders(compOrderLine, requestContext)) .compose(v -> expenseClassValidationService.validateExpenseClassesForOpenedOrder(compOrder, Collections.singletonList(compOrderLine), requestContext)) - .compose(v -> processPoLineEncumbrances(compOrder, compOrderLine, poLineFromStorage, requestContext))) - .map(v -> compOrderLine.withPoLineNumber(poLineFromStorage.getPoLineNumber())) // PoLine number must not be modified during PoLine update, set original value - .map(v -> new PoLineInvoiceLineHolder(compOrderLine, poLineFromStorage)) - .compose(poLineInvoiceLineHolder -> polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext) - .compose(v -> createShadowInstanceIfNeeded(compOrderLine, requestContext)) - .compose(v -> updateOrderLine(compOrderLine, JsonObject.mapFrom(poLineFromStorage), requestContext)) - .compose(v -> updateEncumbranceStatus(compOrderLine, poLineFromStorage, requestContext)) - .compose(v -> polInvoiceLineRelationService.updateInvoiceLineReference(poLineInvoiceLineHolder, requestContext)) - .compose(v -> updateInventoryItemStatus(compOrderLine, poLineFromStorage, requestContext)) - .compose(v -> updateOrderStatusIfNeeded(compOrderLine, poLineFromStorage, requestContext)))); + .compose(v -> processPoLineEncumbrances(compOrder, compOrderLine, poLineFromStorage, requestContext)) + .map(v -> compOrderLine.withPoLineNumber(poLineFromStorage.getPoLineNumber())) // PoLine number must not be modified during PoLine update, set original value + .map(v -> new PoLineInvoiceLineHolder(compOrderLine, poLineFromStorage)) + .compose(poLineInvoiceLineHolder -> polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext) + .compose(v -> createShadowInstanceIfNeeded(compOrderLine, requestContext)) + .compose(v -> updateOrderLine(compOrderLine, JsonObject.mapFrom(poLineFromStorage), requestContext)) + .compose(v -> updateEncumbranceStatus(compOrderLine, poLineFromStorage, requestContext)) + .compose(v -> polInvoiceLineRelationService.updateInvoiceLineReference(poLineInvoiceLineHolder, requestContext)) + .compose(v -> updateInventoryItemStatus(compOrderLine, poLineFromStorage, requestContext)) + .compose(v -> updateOrderStatusIfNeeded(compOrder, compOrderLine, poLineFromStorage, requestContext))))); } private Future<Void> updateEncumbranceStatus(CompositePoLine compOrderLine, PoLine poLineFromStorage, RequestContext requestContext) { @@ -626,7 +626,8 @@ private Future<CompositePoLine> getLineWithInstanceId(CompositePoLine line, Requ if (Boolean.TRUE.equals(line.getIsPackage())) { return Future.succeededFuture(line); } - return titlesService.getTitles(1, 0, QUERY_BY_PO_LINE_ID + line.getId(), requestContext) + var query = String.format(QUERY_BY_PO_LINE_ID, line.getId()); + return titlesService.getTitles(1, 0, query, requestContext) .map(titleCollection -> { var titles = titleCollection.getTitles(); if (!titles.isEmpty()) { diff --git a/src/main/java/org/folio/service/orders/utils/StatusUtils.java b/src/main/java/org/folio/service/orders/utils/StatusUtils.java index dbbec5e8f..d5ec49ead 100644 --- a/src/main/java/org/folio/service/orders/utils/StatusUtils.java +++ b/src/main/java/org/folio/service/orders/utils/StatusUtils.java @@ -8,18 +8,26 @@ import org.folio.orders.utils.HelperUtils; import org.folio.rest.core.models.RequestContext; import org.folio.rest.jaxrs.model.CompositePoLine; +import org.folio.rest.jaxrs.model.CompositePoLine.PaymentStatus; +import org.folio.rest.jaxrs.model.CompositePoLine.ReceiptStatus; +import org.folio.rest.jaxrs.model.CompositePurchaseOrder; import org.folio.rest.jaxrs.model.PoLine; import java.util.List; +import java.util.Set; import static org.folio.helper.BaseHelper.EVENT_PAYLOAD; import static org.folio.helper.BaseHelper.ORDER_ID; public class StatusUtils { - public static Future<Void> updateOrderStatusIfNeeded(CompositePoLine compOrderLine, PoLine poLineFromStorage, RequestContext requestContext) { + private static final Set<PaymentStatus> resolutionPaymentStatus = Set.of(PaymentStatus.CANCELLED, PaymentStatus.FULLY_PAID, PaymentStatus.PAYMENT_NOT_REQUIRED); + private static final Set<ReceiptStatus> resolutionReceiptStatus = Set.of(ReceiptStatus.CANCELLED, ReceiptStatus.FULLY_RECEIVED, ReceiptStatus.RECEIPT_NOT_REQUIRED); + + public static Future<Void> updateOrderStatusIfNeeded(CompositePurchaseOrder compositePurchaseOrder, CompositePoLine compOrderLine, + PoLine poLineFromStorage, RequestContext requestContext) { // See MODORDERS-218 - if (isStatusChanged(compOrderLine, poLineFromStorage)) { + if (isStatusChanged(compOrderLine, poLineFromStorage) && shouldUpdateOrderStatus(compositePurchaseOrder, compOrderLine)) { var updateOrderMessage = JsonObject.of(EVENT_PAYLOAD, JsonArray.of(JsonObject.of(ORDER_ID, compOrderLine.getPurchaseOrderId()))); HelperUtils.sendEvent(MessageAddress.RECEIVE_ORDER_STATUS_UPDATE, updateOrderMessage, requestContext); } @@ -31,9 +39,10 @@ public static boolean isStatusChanged(CompositePoLine compOrderLine, PoLine line !StringUtils.equals(lineFromStorage.getPaymentStatus().value(), compOrderLine.getPaymentStatus().value()); } - public static boolean shouldUpdateOrderStatus(CompositePoLine compOrderLine, PoLine lineFromStorage) { - return !StringUtils.equals(lineFromStorage.getReceiptStatus().value(), compOrderLine.getReceiptStatus().value()) || - !StringUtils.equals(lineFromStorage.getPaymentStatus().value(), compOrderLine.getPaymentStatus().value()); + private static boolean shouldUpdateOrderStatus(CompositePurchaseOrder compositePurchaseOrder, CompositePoLine compOrderLine) { + return compositePurchaseOrder.getWorkflowStatus() != CompositePurchaseOrder.WorkflowStatus.CLOSED + && !resolutionPaymentStatus.contains(compOrderLine.getPaymentStatus()) + && !resolutionReceiptStatus.contains(compOrderLine.getReceiptStatus()); } public static boolean areAllPoLinesCanceled(List<PoLine> poLines) { From 15cbe2a20eeefc8de013b3ead8b3572f1a42732d Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Thu, 19 Sep 2024 20:23:44 +0400 Subject: [PATCH 04/11] [MODORDERS-1143] Fix failing tests --- .../folio/helper/PurchaseOrderLineHelper.java | 18 +++++++++++------- .../org/folio/orders/utils/HelperUtils.java | 7 +++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index b95a01560..5083c334e 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -1,10 +1,11 @@ package org.folio.helper; -import static io.vertx.core.json.JsonObject.mapFrom; import static org.apache.commons.collections4.CollectionUtils.isEqualCollection; import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import static org.apache.commons.collections4.CollectionUtils.isEmpty; import static org.folio.orders.utils.HelperUtils.calculateEstimatedPrice; +import static org.folio.orders.utils.HelperUtils.convertToCompositePoLine; +import static org.folio.orders.utils.HelperUtils.convertToPoLine; import static org.folio.orders.utils.HelperUtils.getPoLineLimit; import static org.folio.orders.utils.PoLineCommonUtil.verifyProtectedFieldsChanged; import static org.folio.orders.utils.ProtectedOperationType.DELETE; @@ -209,7 +210,7 @@ public Future<CompositePoLine> createPoLineWithOrder(CompositePoLine compPoLine, updateEstimatedPrice(compPoLine); PoLineCommonUtil.updateLocationsQuantity(compPoLine.getLocations()); - var line = mapFrom(compPoLine).mapTo(PoLine.class); + var line = convertToPoLine(compPoLine); List<Future<Void>> subObjFuts = new ArrayList<>(); subObjFuts.add(createAlerts(compPoLine, line, requestContext)); subObjFuts.add(createReportingCodes(compPoLine, line, requestContext)); @@ -446,11 +447,14 @@ public Future<Void> updatePoLines(CompositePurchaseOrder poFromStorage, Composit if (poFromStorage.getWorkflowStatus() != PENDING && getNewPoLines(compPO, existingPoLines).findAny().isPresent()) { throw new HttpException(422, poFromStorage.getWorkflowStatus() == OPEN ? ErrorCodes.ORDER_OPEN : ErrorCodes.ORDER_CLOSED); } - validatePoLineProtectedFieldsChangedOrder(compPO, existingPoLines); + validatePoLineProtectedFieldsChangedOrder(poFromStorage, compPO, existingPoLines); return handlePoLines(compPO, existingPoLines, requestContext); } - private void validatePoLineProtectedFieldsChangedOrder(CompositePurchaseOrder compPO, List<PoLine> existingPoLines) { + private void validatePoLineProtectedFieldsChangedOrder(CompositePurchaseOrder poFromStorage, CompositePurchaseOrder compPO, List<PoLine> existingPoLines) { + if (poFromStorage.getWorkflowStatus() == PENDING) { + return; + } compPO.getCompositePoLines().forEach(poLine -> { var fields = POLineProtectedFieldsUtil.getFieldNames(poLine.getOrderFormat().value()); var correspondingLine = findCorrespondingCompositePoLine(poLine, existingPoLines); @@ -637,8 +641,8 @@ private Future<CompositePoLine> getLineWithInstanceId(CompositePoLine line, Requ }); } - private CompositePurchaseOrder addLineToCompOrder(CompositePurchaseOrder compOrder, PoLine poLine) { - var compPoLine = JsonObject.mapFrom(poLine.withAlerts(null).withReportingCodes(null)).mapTo(CompositePoLine.class); + private CompositePurchaseOrder addLineToCompOrder(CompositePurchaseOrder compOrder, PoLine lineFromStorage) { + var compPoLine = convertToCompositePoLine(lineFromStorage); compOrder.getCompositePoLines().add(compPoLine); return compOrder; } @@ -718,7 +722,7 @@ static boolean hasAlteredExchangeRate(Cost oldCost, Cost newCost) { private Future<Void> validateAccessProviders(CompositePoLine compOrderLine, RequestContext requestContext) { return organizationService.validateAccessProviders(Collections.singletonList(compOrderLine), requestContext) .map(errors -> { - if (!isNotEmpty(errors.getErrors())) { + if (isNotEmpty(errors.getErrors())) { throw new HttpException(422, errors.getErrors().get(0)); } return null; diff --git a/src/main/java/org/folio/orders/utils/HelperUtils.java b/src/main/java/org/folio/orders/utils/HelperUtils.java index e0ca60a3e..872d085b6 100644 --- a/src/main/java/org/folio/orders/utils/HelperUtils.java +++ b/src/main/java/org/folio/orders/utils/HelperUtils.java @@ -448,6 +448,13 @@ private static boolean isCompletedPoLine(PoLine line) { && (receiptStatus == FULLY_RECEIVED || receiptStatus == RECEIPT_NOT_REQUIRED || receiptStatus == ReceiptStatus.CANCELLED); } + public static CompositePoLine convertToCompositePoLine(PoLine poLine) { + JsonObject pol = JsonObject.mapFrom(poLine); + pol.remove(ALERTS); + pol.remove(REPORTING_CODES); + return pol.mapTo(CompositePoLine.class); + } + public static PoLine convertToPoLine(CompositePoLine compPoLine) { JsonObject pol = JsonObject.mapFrom(compPoLine); pol.remove(ALERTS); From 5081d028dd6cc29ac65c9fd1cf4ab0ff2968383a Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Fri, 20 Sep 2024 13:59:38 +0400 Subject: [PATCH 05/11] [MODORDERS-1174] Simplify status change logic --- .../org/folio/helper/PurchaseOrderHelper.java | 2 +- .../folio/helper/PurchaseOrderLineHelper.java | 19 ++- .../handlers/AbstractOrderStatusHandler.java | 6 +- .../org/folio/orders/utils/HelperUtils.java | 50 -------- .../service/orders/utils/StatusUtils.java | 115 ++++++++++++------ .../folio/orders/utils/HelperUtilsTest.java | 3 +- 6 files changed, 103 insertions(+), 92 deletions(-) diff --git a/src/main/java/org/folio/helper/PurchaseOrderHelper.java b/src/main/java/org/folio/helper/PurchaseOrderHelper.java index 168f67ad3..62d183862 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderHelper.java @@ -6,7 +6,6 @@ import static org.folio.orders.utils.HelperUtils.ORDER_CONFIG_MODULE_NAME; import static org.folio.orders.utils.HelperUtils.REASON_CANCELLED; import static org.folio.orders.utils.HelperUtils.WORKFLOW_STATUS; -import static org.folio.orders.utils.HelperUtils.changeOrderStatus; import static org.folio.orders.utils.HelperUtils.collectResultsOnSuccess; import static org.folio.orders.utils.HelperUtils.convertToCompositePurchaseOrder; import static org.folio.orders.utils.OrderStatusTransitionUtil.isOrderClosing; @@ -24,6 +23,7 @@ import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.OPEN; import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.PENDING; import static org.folio.service.UserService.getCurrentUserId; +import static org.folio.service.orders.utils.StatusUtils.changeOrderStatus; import java.util.Arrays; import java.util.List; diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index 5083c334e..d8b1353e5 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -3,6 +3,8 @@ import static org.apache.commons.collections4.CollectionUtils.isEqualCollection; import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import static org.apache.commons.collections4.CollectionUtils.isEmpty; +import static org.folio.helper.BaseHelper.EVENT_PAYLOAD; +import static org.folio.helper.BaseHelper.ORDER_ID; import static org.folio.orders.utils.HelperUtils.calculateEstimatedPrice; import static org.folio.orders.utils.HelperUtils.convertToCompositePoLine; import static org.folio.orders.utils.HelperUtils.convertToPoLine; @@ -20,9 +22,8 @@ import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.OPEN; import static org.folio.rest.jaxrs.model.CompositePurchaseOrder.WorkflowStatus.PENDING; import static org.folio.service.orders.utils.StatusUtils.areAllPoLinesCanceled; -import static org.folio.service.orders.utils.StatusUtils.isCompositePoLineStatusCanceled; +import static org.folio.service.orders.utils.StatusUtils.isStatusCanceledCompositePoLine; import static org.folio.service.orders.utils.StatusUtils.isStatusChanged; -import static org.folio.service.orders.utils.StatusUtils.updateOrderStatusIfNeeded; import java.util.ArrayList; import java.util.Collections; @@ -37,6 +38,7 @@ import javax.ws.rs.core.Response; +import io.vertx.core.json.JsonArray; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; @@ -44,6 +46,7 @@ import org.folio.models.ItemStatus; import org.folio.models.PoLineInvoiceLineHolder; import org.folio.okapi.common.GenericCompositeFuture; +import org.folio.orders.events.handlers.MessageAddress; import org.folio.orders.utils.HelperUtils; import org.folio.orders.utils.POLineProtectedFieldsUtil; import org.folio.orders.utils.PoLineCommonUtil; @@ -672,7 +675,7 @@ private Future<Void> processPoLineEncumbrances(CompositePurchaseOrder compOrder, } private Future<Void> updateInventoryItemStatus(CompositePoLine compOrderLine, PoLine lineFromStorage, RequestContext requestContext) { - if (!isStatusChanged(compOrderLine, lineFromStorage) || !isCompositePoLineStatusCanceled(compOrderLine)) { + if (!isStatusChanged(compOrderLine, lineFromStorage) || !isStatusCanceledCompositePoLine(compOrderLine)) { return Future.succeededFuture(); } return purchaseOrderLineService.getPoLinesByOrderId(compOrderLine.getPurchaseOrderId(), requestContext) @@ -686,6 +689,16 @@ private Future<Void> updateInventoryItemStatus(CompositePoLine compOrderLine, Po }); } + public Future<Void> updateOrderStatusIfNeeded(CompositePurchaseOrder compositePurchaseOrder, CompositePoLine compOrderLine, + PoLine poLineFromStorage, RequestContext requestContext) { + // See MODORDERS-218 + if (isStatusChanged(compOrderLine, poLineFromStorage)) { + var updateOrderMessage = JsonObject.of(EVENT_PAYLOAD, JsonArray.of(JsonObject.of(ORDER_ID, compOrderLine.getPurchaseOrderId()))); + HelperUtils.sendEvent(MessageAddress.RECEIVE_ORDER_STATUS_UPDATE, updateOrderMessage, requestContext); + } + return Future.succeededFuture(); + } + private boolean isEncumbranceUpdateNeeded(CompositePurchaseOrder compOrder, CompositePoLine compositePoLine, PoLine storagePoLine) { List<FundDistribution> requestFundDistros = compositePoLine.getFundDistribution(); List<FundDistribution> storageFundDistros = storagePoLine.getFundDistribution(); diff --git a/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java b/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java index b4ed22894..cb1c48350 100644 --- a/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java +++ b/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java @@ -1,7 +1,7 @@ package org.folio.orders.events.handlers; -import static org.folio.orders.utils.HelperUtils.changeOrderStatus; import static org.folio.orders.utils.HelperUtils.getOkapiHeaders; +import static org.folio.service.orders.utils.StatusUtils.changeOrderStatus; import java.util.ArrayList; import java.util.List; @@ -10,8 +10,8 @@ import org.folio.completablefuture.AsyncUtil; import org.folio.helper.BaseHelper; import org.folio.helper.PurchaseOrderHelper; +import org.folio.orders.utils.HelperUtils; import org.folio.rest.core.models.RequestContext; -import org.folio.rest.jaxrs.model.CompositePoLine; import org.folio.rest.jaxrs.model.CompositePurchaseOrder; import org.folio.rest.jaxrs.model.PoLine; import org.folio.rest.jaxrs.model.PurchaseOrder; @@ -108,7 +108,7 @@ protected JsonArray messageAsJsonArray(String rootElement, Message<JsonObject> m } protected CompositePurchaseOrder convert(PurchaseOrder po, List<PoLine> poLines) { - var lines = poLines.stream().map(line -> JsonObject.mapFrom(line).mapTo(CompositePoLine.class)).toList(); + var lines = poLines.stream().map(HelperUtils::convertToCompositePoLine).toList(); return JsonObject.mapFrom(po).mapTo(CompositePurchaseOrder.class).withCompositePoLines(lines); } diff --git a/src/main/java/org/folio/orders/utils/HelperUtils.java b/src/main/java/org/folio/orders/utils/HelperUtils.java index 872d085b6..e470c725f 100644 --- a/src/main/java/org/folio/orders/utils/HelperUtils.java +++ b/src/main/java/org/folio/orders/utils/HelperUtils.java @@ -393,61 +393,11 @@ public static CompositePurchaseOrder convertToCompositePurchaseOrder(JsonObject return poJson.mapTo(CompositePurchaseOrder.class); } - public static boolean changeOrderStatus(PurchaseOrder purchaseOrder, List<PoLine> poLines) { - if (toBeCancelled(purchaseOrder, poLines)) { - purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.CLOSED); - purchaseOrder.setCloseReason(new CloseReason().withReason(REASON_CANCELLED)); - return true; - } - - if (toBeClosed(purchaseOrder, poLines)) { - purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.CLOSED); - purchaseOrder.setCloseReason(new CloseReason().withReason(REASON_COMPLETE)); - return true; - } - - if (toBeReopened(purchaseOrder, poLines)) { - purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN); - return true; - } - - return false; - } - public static String convertTagListToCqlQuery(Collection<String> values, String fieldName, boolean strictMatch) { - String prefix = fieldName + (strictMatch ? "==(\"" : "=(\""); return StreamEx.of(values).joining("\" or \"", prefix, "\")"); } - private static boolean toBeClosed(PurchaseOrder purchaseOrder, List<PoLine> poLines) { - return purchaseOrder.getWorkflowStatus() == PurchaseOrder.WorkflowStatus.OPEN - && poLines.stream().allMatch(HelperUtils::isCompletedPoLine); - } - - private static boolean toBeCancelled(PurchaseOrder purchaseOrder, List<PoLine> poLines) { - return purchaseOrder.getWorkflowStatus() == PurchaseOrder.WorkflowStatus.OPEN - && poLines.stream().allMatch(HelperUtils::isCancelledPoLine); - } - - private static boolean isCancelledPoLine(PoLine line) { - PoLine.PaymentStatus paymentStatus = line.getPaymentStatus(); - PoLine.ReceiptStatus receiptStatus = line.getReceiptStatus(); - return paymentStatus == PaymentStatus.CANCELLED && receiptStatus == ReceiptStatus.CANCELLED; - } - - private static boolean toBeReopened(PurchaseOrder purchaseOrder, List<PoLine> poLines) { - return purchaseOrder.getWorkflowStatus() == PurchaseOrder.WorkflowStatus.CLOSED - && poLines.stream().anyMatch(line -> !isCompletedPoLine(line)); - } - - private static boolean isCompletedPoLine(PoLine line) { - PoLine.PaymentStatus paymentStatus = line.getPaymentStatus(); - PoLine.ReceiptStatus receiptStatus = line.getReceiptStatus(); - return (paymentStatus == PAYMENT_NOT_REQUIRED || paymentStatus == FULLY_PAID || paymentStatus == PaymentStatus.CANCELLED) - && (receiptStatus == FULLY_RECEIVED || receiptStatus == RECEIPT_NOT_REQUIRED || receiptStatus == ReceiptStatus.CANCELLED); - } - public static CompositePoLine convertToCompositePoLine(PoLine poLine) { JsonObject pol = JsonObject.mapFrom(poLine); pol.remove(ALERTS); diff --git a/src/main/java/org/folio/service/orders/utils/StatusUtils.java b/src/main/java/org/folio/service/orders/utils/StatusUtils.java index d5ec49ead..a97aee9f7 100644 --- a/src/main/java/org/folio/service/orders/utils/StatusUtils.java +++ b/src/main/java/org/folio/service/orders/utils/StatusUtils.java @@ -1,62 +1,109 @@ package org.folio.service.orders.utils; -import io.vertx.core.Future; -import io.vertx.core.json.JsonArray; -import io.vertx.core.json.JsonObject; import org.apache.commons.lang3.StringUtils; -import org.folio.orders.events.handlers.MessageAddress; -import org.folio.orders.utils.HelperUtils; -import org.folio.rest.core.models.RequestContext; +import org.folio.rest.jaxrs.model.CloseReason; import org.folio.rest.jaxrs.model.CompositePoLine; -import org.folio.rest.jaxrs.model.CompositePoLine.PaymentStatus; -import org.folio.rest.jaxrs.model.CompositePoLine.ReceiptStatus; -import org.folio.rest.jaxrs.model.CompositePurchaseOrder; import org.folio.rest.jaxrs.model.PoLine; +import org.folio.rest.jaxrs.model.PoLine.PaymentStatus; +import org.folio.rest.jaxrs.model.PoLine.ReceiptStatus; +import org.folio.rest.jaxrs.model.PurchaseOrder; import java.util.List; import java.util.Set; -import static org.folio.helper.BaseHelper.EVENT_PAYLOAD; -import static org.folio.helper.BaseHelper.ORDER_ID; +import static org.folio.orders.utils.HelperUtils.REASON_CANCELLED; +import static org.folio.orders.utils.HelperUtils.REASON_COMPLETE; public class StatusUtils { - private static final Set<PaymentStatus> resolutionPaymentStatus = Set.of(PaymentStatus.CANCELLED, PaymentStatus.FULLY_PAID, PaymentStatus.PAYMENT_NOT_REQUIRED); - private static final Set<ReceiptStatus> resolutionReceiptStatus = Set.of(ReceiptStatus.CANCELLED, ReceiptStatus.FULLY_RECEIVED, ReceiptStatus.RECEIPT_NOT_REQUIRED); + private static final Set<String> resolutionPaymentStatus = Set.of(PaymentStatus.CANCELLED.value(), PaymentStatus.PAYMENT_NOT_REQUIRED.value(), PaymentStatus.FULLY_PAID.value()); + private static final Set<String> resolutionReceiptStatus = Set.of(ReceiptStatus.CANCELLED.value(), ReceiptStatus.RECEIPT_NOT_REQUIRED.value(), ReceiptStatus.FULLY_RECEIVED.value()); - public static Future<Void> updateOrderStatusIfNeeded(CompositePurchaseOrder compositePurchaseOrder, CompositePoLine compOrderLine, - PoLine poLineFromStorage, RequestContext requestContext) { - // See MODORDERS-218 - if (isStatusChanged(compOrderLine, poLineFromStorage) && shouldUpdateOrderStatus(compositePurchaseOrder, compOrderLine)) { - var updateOrderMessage = JsonObject.of(EVENT_PAYLOAD, JsonArray.of(JsonObject.of(ORDER_ID, compOrderLine.getPurchaseOrderId()))); - HelperUtils.sendEvent(MessageAddress.RECEIVE_ORDER_STATUS_UPDATE, updateOrderMessage, requestContext); - } - return Future.succeededFuture(); - } + +// private static boolean isCompositeOrderClosed(CompositePurchaseOrder order) { +// return order.getWorkflowStatus() == CompositePurchaseOrder.WorkflowStatus.CLOSED; +// } public static boolean isStatusChanged(CompositePoLine compOrderLine, PoLine lineFromStorage) { return !StringUtils.equals(lineFromStorage.getReceiptStatus().value(), compOrderLine.getReceiptStatus().value()) || !StringUtils.equals(lineFromStorage.getPaymentStatus().value(), compOrderLine.getPaymentStatus().value()); } - private static boolean shouldUpdateOrderStatus(CompositePurchaseOrder compositePurchaseOrder, CompositePoLine compOrderLine) { - return compositePurchaseOrder.getWorkflowStatus() != CompositePurchaseOrder.WorkflowStatus.CLOSED - && !resolutionPaymentStatus.contains(compOrderLine.getPaymentStatus()) - && !resolutionReceiptStatus.contains(compOrderLine.getReceiptStatus()); - } +// public static boolean shouldUpdateOrderStatus(CompositePurchaseOrder compositePurchaseOrder, CompositePoLine compOrderLine, PoLine lineFromStorage) { +// return !isCompositeOrderClosed(compositePurchaseOrder) && isStatusChanged(compOrderLine, lineFromStorage) +// || isCompositeOrderClosed(compositePurchaseOrder) && isNonResolutionPoLine(compOrderLine); +// } public static boolean areAllPoLinesCanceled(List<PoLine> poLines) { - return poLines.stream().allMatch(StatusUtils::isPoLineStatusCanceled); + return poLines.stream().allMatch(StatusUtils::isStatusCanceledPoLine); + } + + public static boolean changeOrderStatus(PurchaseOrder purchaseOrder, List<PoLine> poLines) { + if (toBeCancelled(purchaseOrder, poLines)) { + purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.CLOSED); + purchaseOrder.setCloseReason(new CloseReason().withReason(REASON_CANCELLED)); + return true; + } + if (toBeClosed(purchaseOrder, poLines)) { + purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.CLOSED); + purchaseOrder.setCloseReason(new CloseReason().withReason(REASON_COMPLETE)); + return true; + } + if (toBeReopened(purchaseOrder, poLines)) { + purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN); + return true; + } + return false; + } + + private static boolean toBeClosed(PurchaseOrder purchaseOrder, List<PoLine> poLines) { + return isOrderOpen(purchaseOrder) + && poLines.stream().allMatch(StatusUtils::isCompletedPoLine); + } + + private static boolean toBeCancelled(PurchaseOrder purchaseOrder, List<PoLine> poLines) { + return isOrderOpen(purchaseOrder) + && poLines.stream().allMatch(StatusUtils::isCancelledPoLine); } - private static boolean isPoLineStatusCanceled(PoLine poLine) { - return PoLine.PaymentStatus.CANCELLED.equals(poLine.getPaymentStatus()) || - PoLine.ReceiptStatus.CANCELLED.equals(poLine.getReceiptStatus()); + private static boolean toBeReopened(PurchaseOrder purchaseOrder, List<PoLine> poLines) { + return isOrderClosed(purchaseOrder) + && poLines.stream().anyMatch(StatusUtils::isNonResolutionPoLine); } - public static boolean isCompositePoLineStatusCanceled(CompositePoLine compOrderLine) { - return CompositePoLine.ReceiptStatus.CANCELLED.equals(compOrderLine.getReceiptStatus()) || - CompositePoLine.PaymentStatus.CANCELLED.equals(compOrderLine.getPaymentStatus()); + private static boolean isCompletedPoLine(PoLine line) { + return resolutionPaymentStatus.contains(line.getPaymentStatus().value()) + && resolutionReceiptStatus.contains(line.getReceiptStatus().value()); } + private static boolean isNonResolutionPoLine(PoLine line) { + return !resolutionPaymentStatus.contains(line.getPaymentStatus().value()) + && !resolutionReceiptStatus.contains(line.getReceiptStatus().value()); + } + + private static boolean isCancelledPoLine(PoLine poLine) { + return poLine.getPaymentStatus() == PoLine.PaymentStatus.CANCELLED + && poLine.getReceiptStatus() == PoLine.ReceiptStatus.CANCELLED; + } + + private static boolean isStatusCanceledPoLine(PoLine poLine) { + return poLine.getPaymentStatus() == PoLine.PaymentStatus.CANCELLED + || poLine.getReceiptStatus() == PoLine.ReceiptStatus.CANCELLED; + } + + public static boolean isStatusCanceledCompositePoLine(CompositePoLine compOrderLine) { + return compOrderLine.getReceiptStatus() == CompositePoLine.ReceiptStatus.CANCELLED + || compOrderLine.getPaymentStatus() == CompositePoLine.PaymentStatus.CANCELLED; + } + + private static boolean isOrderOpen(PurchaseOrder order) { + return order.getWorkflowStatus() == PurchaseOrder.WorkflowStatus.OPEN; + } + + private static boolean isOrderClosed(PurchaseOrder order) { + return order.getWorkflowStatus() == PurchaseOrder.WorkflowStatus.CLOSED; + } + + private StatusUtils() {} + } diff --git a/src/test/java/org/folio/orders/utils/HelperUtilsTest.java b/src/test/java/org/folio/orders/utils/HelperUtilsTest.java index 2ab275f8e..b050517bd 100644 --- a/src/test/java/org/folio/orders/utils/HelperUtilsTest.java +++ b/src/test/java/org/folio/orders/utils/HelperUtilsTest.java @@ -5,6 +5,7 @@ import org.folio.rest.jaxrs.model.CloseReason; import org.folio.rest.jaxrs.model.PoLine; import org.folio.rest.jaxrs.model.PurchaseOrder; +import org.folio.service.orders.utils.StatusUtils; import org.junit.jupiter.api.Test; import javax.money.convert.ConversionQuery; @@ -92,7 +93,7 @@ void testOrderStatusToBeCancelled() { List<PoLine> poLines = List.of(firstPoLine, secondPoLine); - assertTrue(HelperUtils.changeOrderStatus(purchaseOrder, poLines)); + assertTrue(StatusUtils.changeOrderStatus(purchaseOrder, poLines)); assertEquals(purchaseOrder.getWorkflowStatus(), PurchaseOrder.WorkflowStatus.CLOSED); assertEquals(purchaseOrder.getCloseReason(), new CloseReason().withReason(REASON_CANCELLED)); } From d877adb90d8f09f52fcbac7bda9536a670329a3f Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Fri, 20 Sep 2024 14:29:52 +0400 Subject: [PATCH 06/11] [MODORDERS-1174] Cleanup --- .../folio/helper/PurchaseOrderLineHelper.java | 23 +++++++++---------- .../org/folio/orders/utils/HelperUtils.java | 7 ------ .../service/orders/utils/StatusUtils.java | 10 -------- 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index d8b1353e5..f3176e511 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -289,16 +289,16 @@ public Future<Void> updateOrderLine(CompositePoLine compOrderLine, RequestContex .compose(v -> purchaseOrderLineService.validateAndNormalizeISBNAndProductType(Collections.singletonList(compOrderLine), requestContext)) .compose(v -> validateAccessProviders(compOrderLine, requestContext)) .compose(v -> expenseClassValidationService.validateExpenseClassesForOpenedOrder(compOrder, Collections.singletonList(compOrderLine), requestContext)) - .compose(v -> processPoLineEncumbrances(compOrder, compOrderLine, poLineFromStorage, requestContext)) - .map(v -> compOrderLine.withPoLineNumber(poLineFromStorage.getPoLineNumber())) // PoLine number must not be modified during PoLine update, set original value - .map(v -> new PoLineInvoiceLineHolder(compOrderLine, poLineFromStorage)) - .compose(poLineInvoiceLineHolder -> polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext) - .compose(v -> createShadowInstanceIfNeeded(compOrderLine, requestContext)) - .compose(v -> updateOrderLine(compOrderLine, JsonObject.mapFrom(poLineFromStorage), requestContext)) - .compose(v -> updateEncumbranceStatus(compOrderLine, poLineFromStorage, requestContext)) - .compose(v -> polInvoiceLineRelationService.updateInvoiceLineReference(poLineInvoiceLineHolder, requestContext)) - .compose(v -> updateInventoryItemStatus(compOrderLine, poLineFromStorage, requestContext)) - .compose(v -> updateOrderStatusIfNeeded(compOrder, compOrderLine, poLineFromStorage, requestContext))))); + .compose(v -> processPoLineEncumbrances(compOrder, compOrderLine, poLineFromStorage, requestContext))) + .map(v -> compOrderLine.withPoLineNumber(poLineFromStorage.getPoLineNumber())) // PoLine number must not be modified during PoLine update, set original value + .map(v -> new PoLineInvoiceLineHolder(compOrderLine, poLineFromStorage)) + .compose(poLineInvoiceLineHolder -> polInvoiceLineRelationService.prepareRelatedInvoiceLines(poLineInvoiceLineHolder, requestContext) + .compose(v -> createShadowInstanceIfNeeded(compOrderLine, requestContext)) + .compose(v -> updateOrderLine(compOrderLine, JsonObject.mapFrom(poLineFromStorage), requestContext)) + .compose(v -> updateEncumbranceStatus(compOrderLine, poLineFromStorage, requestContext)) + .compose(v -> polInvoiceLineRelationService.updateInvoiceLineReference(poLineInvoiceLineHolder, requestContext)) + .compose(v -> updateInventoryItemStatus(compOrderLine, poLineFromStorage, requestContext)) + .compose(v -> updateOrderStatusIfNeeded(compOrderLine, poLineFromStorage, requestContext)))); } private Future<Void> updateEncumbranceStatus(CompositePoLine compOrderLine, PoLine poLineFromStorage, RequestContext requestContext) { @@ -689,8 +689,7 @@ private Future<Void> updateInventoryItemStatus(CompositePoLine compOrderLine, Po }); } - public Future<Void> updateOrderStatusIfNeeded(CompositePurchaseOrder compositePurchaseOrder, CompositePoLine compOrderLine, - PoLine poLineFromStorage, RequestContext requestContext) { + public Future<Void> updateOrderStatusIfNeeded(CompositePoLine compOrderLine, PoLine poLineFromStorage, RequestContext requestContext) { // See MODORDERS-218 if (isStatusChanged(compOrderLine, poLineFromStorage)) { var updateOrderMessage = JsonObject.of(EVENT_PAYLOAD, JsonArray.of(JsonObject.of(ORDER_ID, compOrderLine.getPurchaseOrderId()))); diff --git a/src/main/java/org/folio/orders/utils/HelperUtils.java b/src/main/java/org/folio/orders/utils/HelperUtils.java index e470c725f..b7239497f 100644 --- a/src/main/java/org/folio/orders/utils/HelperUtils.java +++ b/src/main/java/org/folio/orders/utils/HelperUtils.java @@ -21,15 +21,12 @@ import org.folio.rest.core.exceptions.NoInventoryRecordException; import org.folio.rest.core.models.RequestContext; import org.folio.rest.jaxrs.model.Alert; -import org.folio.rest.jaxrs.model.CloseReason; import org.folio.rest.jaxrs.model.CompositePoLine; import org.folio.rest.jaxrs.model.CompositePurchaseOrder; import org.folio.rest.jaxrs.model.Cost; import org.folio.rest.jaxrs.model.Location; import org.folio.rest.jaxrs.model.Piece; import org.folio.rest.jaxrs.model.PoLine; -import org.folio.rest.jaxrs.model.PoLine.PaymentStatus; -import org.folio.rest.jaxrs.model.PoLine.ReceiptStatus; import org.folio.rest.jaxrs.model.PurchaseOrder; import org.folio.rest.jaxrs.model.ReportingCode; import org.folio.rest.jaxrs.model.Title; @@ -67,10 +64,6 @@ import static org.folio.rest.RestConstants.EN; import static org.folio.rest.core.exceptions.ErrorCodes.MULTIPLE_NONPACKAGE_TITLES; import static org.folio.rest.core.exceptions.ErrorCodes.TITLE_NOT_FOUND; -import static org.folio.rest.jaxrs.model.PoLine.PaymentStatus.FULLY_PAID; -import static org.folio.rest.jaxrs.model.PoLine.PaymentStatus.PAYMENT_NOT_REQUIRED; -import static org.folio.rest.jaxrs.model.PoLine.ReceiptStatus.FULLY_RECEIVED; -import static org.folio.rest.jaxrs.model.PoLine.ReceiptStatus.RECEIPT_NOT_REQUIRED; public class HelperUtils { diff --git a/src/main/java/org/folio/service/orders/utils/StatusUtils.java b/src/main/java/org/folio/service/orders/utils/StatusUtils.java index a97aee9f7..325bada90 100644 --- a/src/main/java/org/folio/service/orders/utils/StatusUtils.java +++ b/src/main/java/org/folio/service/orders/utils/StatusUtils.java @@ -19,21 +19,11 @@ public class StatusUtils { private static final Set<String> resolutionPaymentStatus = Set.of(PaymentStatus.CANCELLED.value(), PaymentStatus.PAYMENT_NOT_REQUIRED.value(), PaymentStatus.FULLY_PAID.value()); private static final Set<String> resolutionReceiptStatus = Set.of(ReceiptStatus.CANCELLED.value(), ReceiptStatus.RECEIPT_NOT_REQUIRED.value(), ReceiptStatus.FULLY_RECEIVED.value()); - -// private static boolean isCompositeOrderClosed(CompositePurchaseOrder order) { -// return order.getWorkflowStatus() == CompositePurchaseOrder.WorkflowStatus.CLOSED; -// } - public static boolean isStatusChanged(CompositePoLine compOrderLine, PoLine lineFromStorage) { return !StringUtils.equals(lineFromStorage.getReceiptStatus().value(), compOrderLine.getReceiptStatus().value()) || !StringUtils.equals(lineFromStorage.getPaymentStatus().value(), compOrderLine.getPaymentStatus().value()); } -// public static boolean shouldUpdateOrderStatus(CompositePurchaseOrder compositePurchaseOrder, CompositePoLine compOrderLine, PoLine lineFromStorage) { -// return !isCompositeOrderClosed(compositePurchaseOrder) && isStatusChanged(compOrderLine, lineFromStorage) -// || isCompositeOrderClosed(compositePurchaseOrder) && isNonResolutionPoLine(compOrderLine); -// } - public static boolean areAllPoLinesCanceled(List<PoLine> poLines) { return poLines.stream().allMatch(StatusUtils::isStatusCanceledPoLine); } From 14df65f1e457a0bfe97b62a247b426a012180492 Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Fri, 20 Sep 2024 18:08:48 +0400 Subject: [PATCH 07/11] [MODORDERS-1143] Address comments --- .../helper/CheckinReceivePiecesHelper.java | 2 +- .../org/folio/helper/PurchaseOrderHelper.java | 2 +- .../folio/helper/PurchaseOrderLineHelper.java | 46 ++++++------------- .../handlers/AbstractOrderStatusHandler.java | 4 +- .../org/folio/orders/utils/HelperUtils.java | 25 ---------- .../folio/orders/utils/PoLineCommonUtil.java | 28 +++++++++++ .../orders/OrderValidationService.java | 2 +- .../orders/PurchaseOrderLineService.java | 2 +- .../unopen/UnOpenCompositeOrderManager.java | 2 +- .../flows/update/PieceUpdateFlowManager.java | 2 +- 10 files changed, 51 insertions(+), 64 deletions(-) diff --git a/src/main/java/org/folio/helper/CheckinReceivePiecesHelper.java b/src/main/java/org/folio/helper/CheckinReceivePiecesHelper.java index 0429f3f9d..968cddfaa 100644 --- a/src/main/java/org/folio/helper/CheckinReceivePiecesHelper.java +++ b/src/main/java/org/folio/helper/CheckinReceivePiecesHelper.java @@ -415,7 +415,7 @@ private PoLine updateRelatedPoLineDetails(PoLine poLine, updatedLocations++; } - return updatedLocations > 0 ? HelperUtils.convertToPoLine(compositePoLine) : poLine; + return updatedLocations > 0 ? PoLineCommonUtil.convertToPoLine(compositePoLine) : poLine; } /** diff --git a/src/main/java/org/folio/helper/PurchaseOrderHelper.java b/src/main/java/org/folio/helper/PurchaseOrderHelper.java index 62d183862..3c39c92cf 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderHelper.java @@ -282,7 +282,7 @@ public Future<Void> handleFinalOrderStatus(CompositePurchaseOrder compPO, String } else { Future.succeededFuture() .map(v -> { - List<PoLine> poLines = HelperUtils.convertToPoLines(compPO.getCompositePoLines()); + List<PoLine> poLines = PoLineCommonUtil.convertToPoLines(compPO.getCompositePoLines()); if (initialOrdersStatus.equals(compPO.getWorkflowStatus().value())) changeOrderStatus(purchaseOrder, poLines); promise.complete(poLines); diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index f3176e511..f44002d3c 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -6,9 +6,9 @@ import static org.folio.helper.BaseHelper.EVENT_PAYLOAD; import static org.folio.helper.BaseHelper.ORDER_ID; import static org.folio.orders.utils.HelperUtils.calculateEstimatedPrice; -import static org.folio.orders.utils.HelperUtils.convertToCompositePoLine; -import static org.folio.orders.utils.HelperUtils.convertToPoLine; import static org.folio.orders.utils.HelperUtils.getPoLineLimit; +import static org.folio.orders.utils.PoLineCommonUtil.convertToCompositePoLine; +import static org.folio.orders.utils.PoLineCommonUtil.convertToPoLine; import static org.folio.orders.utils.PoLineCommonUtil.verifyProtectedFieldsChanged; import static org.folio.orders.utils.ProtectedOperationType.DELETE; import static org.folio.orders.utils.ProtectedOperationType.UPDATE; @@ -88,7 +88,6 @@ import org.folio.service.titles.TitlesService; import io.vertx.core.Future; -import io.vertx.core.Promise; import io.vertx.core.http.HttpMethod; import io.vertx.core.json.JsonObject; @@ -230,18 +229,12 @@ public Future<Void> setTenantDefaultCreateInventoryValues(CompositePoLine compPO if (!isCreateInventoryNull(compPOL)) { return Future.succeededFuture(); } - - Promise<JsonObject> promise = Promise.promise(); - if (tenantConfiguration != null && !tenantConfiguration.isEmpty() && !StringUtils.isEmpty(tenantConfiguration.getString(CREATE_INVENTORY))) { - promise.complete(new JsonObject(tenantConfiguration.getString(CREATE_INVENTORY))); - } else { - promise.complete(new JsonObject()); + var jsonConfig = new JsonObject(); + if (tenantConfiguration != null && !tenantConfiguration.isEmpty() && StringUtils.isNotEmpty(tenantConfiguration.getString(CREATE_INVENTORY))) { + jsonConfig = new JsonObject(tenantConfiguration.getString(CREATE_INVENTORY)); } - return promise.future() - .map(jsonConfig -> { - updateCreateInventory(compPOL, jsonConfig); - return null; - }); + updateCreateInventory(compPOL, jsonConfig); + return Future.succeededFuture(); } public static boolean isCreateInventoryNull(CompositePoLine compPOL) { @@ -337,17 +330,12 @@ private boolean isUnreleasedEncumbrances(CompositePoLine compOrderLine, PoLine p * @param lineFromStorage {@link JsonObject} representing PO line from storage (/acq-models/mod-orders-storage/schemas/po_line.json) */ public Future<Void> updateOrderLine(CompositePoLine compOrderLine, JsonObject lineFromStorage, RequestContext requestContext) { - Promise<Void> promise = Promise.promise(); - - purchaseOrderLineService.updateSearchLocations(compOrderLine, requestContext) + return purchaseOrderLineService.updateSearchLocations(compOrderLine, requestContext) .compose(v -> purchaseOrderLineService.updatePoLineSubObjects(compOrderLine, lineFromStorage, requestContext)) .compose(poLine -> purchaseOrderLineService.updateOrderLineSummary(compOrderLine.getId(), poLine, requestContext)) - .onSuccess(json -> promise.complete()) .onFailure(throwable -> { logger.error("PoLine with id - '{}' partially updated but there are issues processing some PoLine sub-objects", compOrderLine.getId()); - promise.fail(throwable); - }); - return promise.future(); + }).mapEmpty(); } public String buildNewPoLineNumber(PoLine poLineFromStorage, String poNumber) { @@ -442,7 +430,7 @@ public Future<Void> updatePoLines(CompositePurchaseOrder poFromStorage, Composit if (!isPoLinesUpdateRequired(poFromStorage, compPO)) { return Future.succeededFuture(); } - var existingPoLines = HelperUtils.convertToPoLines(poFromStorage.getCompositePoLines()); + var existingPoLines = PoLineCommonUtil.convertToPoLines(poFromStorage.getCompositePoLines()); if (isEmpty(compPO.getCompositePoLines())) { return updatePoLinesNumber(compPO, existingPoLines, requestContext); } @@ -600,19 +588,14 @@ private Future<List<Error>> validatePoLineLimit(CompositePoLine compPOL, JsonObj } private Future<CompositePurchaseOrder> getCompositePurchaseOrder(String purchaseOrderId, RequestContext requestContext) { - Promise<CompositePurchaseOrder> promise = Promise.promise(); - purchaseOrderStorageService.getPurchaseOrderByIdAsJson(purchaseOrderId, requestContext) + return purchaseOrderStorageService.getPurchaseOrderByIdAsJson(purchaseOrderId, requestContext) .map(HelperUtils::convertToCompositePurchaseOrder) - .onSuccess(promise::complete) .onFailure(cause -> { // The case when specified order does not exist if (cause instanceof HttpException httpException && httpException.getCode() == Response.Status.NOT_FOUND.getStatusCode()) { - cause = new HttpException(422, ErrorCodes.ORDER_NOT_FOUND); + throw new HttpException(422, ErrorCodes.ORDER_NOT_FOUND); } - promise.fail(cause); }); - - return promise.future(); } private Future<String> generateLineNumber(CompositePurchaseOrder compOrder, RequestContext requestContext) { @@ -645,7 +628,7 @@ private Future<CompositePoLine> getLineWithInstanceId(CompositePoLine line, Requ } private CompositePurchaseOrder addLineToCompOrder(CompositePurchaseOrder compOrder, PoLine lineFromStorage) { - var compPoLine = convertToCompositePoLine(lineFromStorage); + var compPoLine = convertToCompositePoLine(JsonObject.mapFrom(lineFromStorage)); compOrder.getCompositePoLines().add(compPoLine); return compOrder; } @@ -675,7 +658,8 @@ private Future<Void> processPoLineEncumbrances(CompositePurchaseOrder compOrder, } private Future<Void> updateInventoryItemStatus(CompositePoLine compOrderLine, PoLine lineFromStorage, RequestContext requestContext) { - if (!isStatusChanged(compOrderLine, lineFromStorage) || !isStatusCanceledCompositePoLine(compOrderLine)) { + var shouldUpdateItemStatus = isStatusChanged(compOrderLine, lineFromStorage) && isStatusCanceledCompositePoLine(compOrderLine); + if (!shouldUpdateItemStatus) { return Future.succeededFuture(); } return purchaseOrderLineService.getPoLinesByOrderId(compOrderLine.getPurchaseOrderId(), requestContext) diff --git a/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java b/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java index cb1c48350..4a0a29f24 100644 --- a/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java +++ b/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java @@ -10,7 +10,7 @@ import org.folio.completablefuture.AsyncUtil; import org.folio.helper.BaseHelper; import org.folio.helper.PurchaseOrderHelper; -import org.folio.orders.utils.HelperUtils; +import org.folio.orders.utils.PoLineCommonUtil; import org.folio.rest.core.models.RequestContext; import org.folio.rest.jaxrs.model.CompositePurchaseOrder; import org.folio.rest.jaxrs.model.PoLine; @@ -108,7 +108,7 @@ protected JsonArray messageAsJsonArray(String rootElement, Message<JsonObject> m } protected CompositePurchaseOrder convert(PurchaseOrder po, List<PoLine> poLines) { - var lines = poLines.stream().map(HelperUtils::convertToCompositePoLine).toList(); + var lines = poLines.stream().map(JsonObject::mapFrom).map(PoLineCommonUtil::convertToCompositePoLine).toList(); return JsonObject.mapFrom(po).mapTo(CompositePurchaseOrder.class).withCompositePoLines(lines); } diff --git a/src/main/java/org/folio/orders/utils/HelperUtils.java b/src/main/java/org/folio/orders/utils/HelperUtils.java index b7239497f..3468e6e40 100644 --- a/src/main/java/org/folio/orders/utils/HelperUtils.java +++ b/src/main/java/org/folio/orders/utils/HelperUtils.java @@ -391,31 +391,6 @@ public static String convertTagListToCqlQuery(Collection<String> values, String return StreamEx.of(values).joining("\" or \"", prefix, "\")"); } - public static CompositePoLine convertToCompositePoLine(PoLine poLine) { - JsonObject pol = JsonObject.mapFrom(poLine); - pol.remove(ALERTS); - pol.remove(REPORTING_CODES); - return pol.mapTo(CompositePoLine.class); - } - - public static PoLine convertToPoLine(CompositePoLine compPoLine) { - JsonObject pol = JsonObject.mapFrom(compPoLine); - pol.remove(ALERTS); - pol.remove(REPORTING_CODES); - PoLine poLine = pol.mapTo(PoLine.class); - poLine.setAlerts(compPoLine.getAlerts().stream().map(Alert::getId).collect(toList())); - poLine.setReportingCodes(compPoLine.getReportingCodes().stream().map(ReportingCode::getId).collect(toList())); - return poLine; - } - - - public static List<PoLine> convertToPoLines(List<CompositePoLine> compositePoLines) { - return compositePoLines - .stream() - .map(HelperUtils::convertToPoLine) - .collect(toList()); - } - public static boolean isProductIdsExist(CompositePoLine compPOL) { return compPOL.getDetails() != null && CollectionUtils.isNotEmpty(compPOL.getDetails().getProductIds()); } diff --git a/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java b/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java index 894c09663..8771e6403 100644 --- a/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java +++ b/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java @@ -1,7 +1,10 @@ package org.folio.orders.utils; +import static java.util.stream.Collectors.toList; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.folio.orders.utils.HelperUtils.calculateTotalLocationQuantity; +import static org.folio.orders.utils.ResourcePathResolver.ALERTS; +import static org.folio.orders.utils.ResourcePathResolver.REPORTING_CODES; import static org.folio.rest.core.exceptions.ErrorCodes.PROHIBITED_FIELD_CHANGING; import static org.folio.rest.core.exceptions.ErrorCodes.WRONG_ONGOING_NOT_SUBSCRIPTION_FIELDS_CHANGED; import static org.folio.rest.core.exceptions.ErrorCodes.WRONG_ONGOING_SUBSCRIPTION_FIELDS_CHANGED; @@ -27,6 +30,7 @@ import org.apache.commons.lang3.ObjectUtils; import org.folio.rest.core.exceptions.HttpException; import org.folio.rest.core.exceptions.ErrorCodes; +import org.folio.rest.jaxrs.model.Alert; import org.folio.rest.jaxrs.model.CompositePoLine; import org.folio.rest.jaxrs.model.CompositePurchaseOrder; import org.folio.rest.jaxrs.model.Eresource; @@ -35,6 +39,7 @@ import org.folio.rest.jaxrs.model.Parameter; import org.folio.rest.jaxrs.model.Physical; import org.folio.rest.jaxrs.model.PoLine; +import org.folio.rest.jaxrs.model.ReportingCode; import org.folio.rest.tools.parser.JsonPathParser; import io.vertx.core.json.JsonArray; @@ -256,6 +261,29 @@ public static CompositePoLine convertToCompositePoLine(PoLine poLine) { return jsonLine.mapTo(CompositePoLine.class); } + public static CompositePoLine convertToCompositePoLine(JsonObject poLine) { + poLine.remove(ALERTS); + poLine.remove(REPORTING_CODES); + return poLine.mapTo(CompositePoLine.class); + } + + public static PoLine convertToPoLine(CompositePoLine compPoLine) { + JsonObject pol = JsonObject.mapFrom(compPoLine); + pol.remove(ALERTS); + pol.remove(REPORTING_CODES); + PoLine poLine = pol.mapTo(PoLine.class); + poLine.setAlerts(compPoLine.getAlerts().stream().map(Alert::getId).collect(toList())); + poLine.setReportingCodes(compPoLine.getReportingCodes().stream().map(ReportingCode::getId).collect(toList())); + return poLine; + } + + public static List<PoLine> convertToPoLines(List<CompositePoLine> compositePoLines) { + return compositePoLines + .stream() + .map(PoLineCommonUtil::convertToPoLine) + .collect(toList()); + } + public static void updateLocationsQuantity(List<Location> locations) { locations.forEach(location -> location.setQuantity(calculateTotalLocationQuantity(location))); } diff --git a/src/main/java/org/folio/service/orders/OrderValidationService.java b/src/main/java/org/folio/service/orders/OrderValidationService.java index 4a54b18cb..805c14f43 100644 --- a/src/main/java/org/folio/service/orders/OrderValidationService.java +++ b/src/main/java/org/folio/service/orders/OrderValidationService.java @@ -292,7 +292,7 @@ private Set<ProtectedOperationType> getInvolvedOperations(CompositePurchaseOrder if (CollectionUtils.isEmpty(compPO.getCompositePoLines())) { return Collections.singleton(UPDATE); } - List<PoLine> poLines = HelperUtils.convertToPoLines(poFromStorage.getCompositePoLines()); + List<PoLine> poLines = PoLineCommonUtil.convertToPoLines(poFromStorage.getCompositePoLines()); Set<String> newIds = compPO.getCompositePoLines().stream().map(CompositePoLine::getId).collect(Collectors.toSet()); Set<String> storageIds = poLines.stream().map(PoLine::getId).collect(Collectors.toSet()); Set<ProtectedOperationType> operations = new HashSet<>(); diff --git a/src/main/java/org/folio/service/orders/PurchaseOrderLineService.java b/src/main/java/org/folio/service/orders/PurchaseOrderLineService.java index 1cc96df3b..88d5ecef6 100644 --- a/src/main/java/org/folio/service/orders/PurchaseOrderLineService.java +++ b/src/main/java/org/folio/service/orders/PurchaseOrderLineService.java @@ -126,7 +126,7 @@ public Future<Void> saveOrderLine(CompositePoLine compositePoLine, RequestContex } public Future<Void> saveOrderLine(CompositePoLine compositePoLine, List<Location> locations, RequestContext requestContext) { - PoLine poLine = HelperUtils.convertToPoLine(compositePoLine); + PoLine poLine = PoLineCommonUtil.convertToPoLine(compositePoLine); return saveOrderLine(poLine, locations, requestContext); } diff --git a/src/main/java/org/folio/service/orders/flows/update/unopen/UnOpenCompositeOrderManager.java b/src/main/java/org/folio/service/orders/flows/update/unopen/UnOpenCompositeOrderManager.java index 5e2bdfa83..6d7c667dd 100644 --- a/src/main/java/org/folio/service/orders/flows/update/unopen/UnOpenCompositeOrderManager.java +++ b/src/main/java/org/folio/service/orders/flows/update/unopen/UnOpenCompositeOrderManager.java @@ -122,7 +122,7 @@ private void makePoLinePending(CompositePoLine poLine) { private Future<Void> updatePoLinesSummary(List<CompositePoLine> compositePoLines, RequestContext requestContext) { return GenericCompositeFuture.join(compositePoLines.stream() - .map(HelperUtils::convertToPoLine) + .map(PoLineCommonUtil::convertToPoLine) .map(line -> purchaseOrderLineService.saveOrderLine(line, requestContext)) .collect(toList())) .map(ok -> null); diff --git a/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowManager.java b/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowManager.java index 7ab437c0a..952eac9f7 100644 --- a/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowManager.java @@ -118,7 +118,7 @@ protected Future<Void> updatePoLine(PieceUpdateHolder holder, RequestContext req } List<Piece> piecesToUpdate = List.of(holder.getPieceToUpdate()); CompositePoLine poLineToSave = holder.getPoLineToSave(); - if (PoLineCommonUtil.isCancelledOrOngoingStatus(HelperUtils.convertToPoLine(poLineToSave))) { + if (PoLineCommonUtil.isCancelledOrOngoingStatus(PoLineCommonUtil.convertToPoLine(poLineToSave))) { logger.info("updatePoLine:: Skipping updating POL '{}' status for CANCELLED or ONGOING po lines", poLineToSave.getId()); } else { poLineToSave.setReceiptStatus(calculatePoLineReceiptStatus(originPoLine, pieces, piecesToUpdate)); From ac0195bd3e0e645db7b9978e43d611988f76104c Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Mon, 23 Sep 2024 13:39:52 +0400 Subject: [PATCH 08/11] [MODORDERS-1143] Remove old method with side effects --- .../folio/helper/CheckinReceivePiecesHelper.java | 2 +- .../folio/helper/PurchaseOrderLineHelper.java | 2 +- .../handlers/AbstractOrderStatusHandler.java | 2 +- .../java/org/folio/orders/utils/HelperUtils.java | 16 +++++----------- .../org/folio/orders/utils/PoLineCommonUtil.java | 14 ++++---------- 5 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/folio/helper/CheckinReceivePiecesHelper.java b/src/main/java/org/folio/helper/CheckinReceivePiecesHelper.java index 968cddfaa..a2f216236 100644 --- a/src/main/java/org/folio/helper/CheckinReceivePiecesHelper.java +++ b/src/main/java/org/folio/helper/CheckinReceivePiecesHelper.java @@ -399,7 +399,7 @@ private PoLine updateRelatedPoLineDetails(PoLine poLine, } short updatedLocations = 0; - CompositePoLine compositePoLine = PoLineCommonUtil.convertToCompositePoLine(poLine); + var compositePoLine = PoLineCommonUtil.convertToCompositePoLine(poLine); for (Piece pieceToUpdate : successfullyProcessed) { Optional<Piece> relatedStoragePiece = piecesFromStorage.stream() .filter(piece -> piece.getId().equals(pieceToUpdate.getId())) diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index f44002d3c..a85d7d6c2 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -628,7 +628,7 @@ private Future<CompositePoLine> getLineWithInstanceId(CompositePoLine line, Requ } private CompositePurchaseOrder addLineToCompOrder(CompositePurchaseOrder compOrder, PoLine lineFromStorage) { - var compPoLine = convertToCompositePoLine(JsonObject.mapFrom(lineFromStorage)); + var compPoLine = convertToCompositePoLine(lineFromStorage); compOrder.getCompositePoLines().add(compPoLine); return compOrder; } diff --git a/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java b/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java index 4a0a29f24..6f241036b 100644 --- a/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java +++ b/src/main/java/org/folio/orders/events/handlers/AbstractOrderStatusHandler.java @@ -108,7 +108,7 @@ protected JsonArray messageAsJsonArray(String rootElement, Message<JsonObject> m } protected CompositePurchaseOrder convert(PurchaseOrder po, List<PoLine> poLines) { - var lines = poLines.stream().map(JsonObject::mapFrom).map(PoLineCommonUtil::convertToCompositePoLine).toList(); + var lines = poLines.stream().map(PoLineCommonUtil::convertToCompositePoLine).toList(); return JsonObject.mapFrom(po).mapTo(CompositePurchaseOrder.class).withCompositePoLines(lines); } diff --git a/src/main/java/org/folio/orders/utils/HelperUtils.java b/src/main/java/org/folio/orders/utils/HelperUtils.java index 3468e6e40..f3b4023f0 100644 --- a/src/main/java/org/folio/orders/utils/HelperUtils.java +++ b/src/main/java/org/folio/orders/utils/HelperUtils.java @@ -468,17 +468,11 @@ public static String extractCreatedDate(JsonObject json) { } public static CompositePurchaseOrder convertToCompositePurchaseOrder(PurchaseOrder purchaseOrder, List<PoLine> poLineList) { - List<CompositePoLine> compositePoLines = new ArrayList<>(poLineList.size()); - if (CollectionUtils.isNotEmpty(poLineList)) { - poLineList.forEach(poLine -> { - poLine.setAlerts(null); - poLine.setReportingCodes(null); - CompositePoLine compositePoLine = PoLineCommonUtil.convertToCompositePoLine(poLine); - compositePoLines.add(compositePoLine); - }); - } - JsonObject jsonLine = JsonObject.mapFrom(purchaseOrder); - return jsonLine.mapTo(CompositePurchaseOrder.class).withCompositePoLines(compositePoLines); + var purchaseOrderJson = JsonObject.mapFrom(purchaseOrder); + var compositePoLines = poLineList.stream() + .map(PoLineCommonUtil::convertToCompositePoLine) + .toList(); + return purchaseOrderJson.mapTo(CompositePurchaseOrder.class).withCompositePoLines(compositePoLines); } public static void sendEvent(MessageAddress messageAddress, JsonObject data, RequestContext requestContext) { diff --git a/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java b/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java index 8771e6403..694c55623 100644 --- a/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java +++ b/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java @@ -255,16 +255,10 @@ public static List<String> getTenantsFromLocations(List<Location> locations) { } public static CompositePoLine convertToCompositePoLine(PoLine poLine) { - poLine.setAlerts(null); - poLine.setReportingCodes(null); - JsonObject jsonLine = JsonObject.mapFrom(poLine); - return jsonLine.mapTo(CompositePoLine.class); - } - - public static CompositePoLine convertToCompositePoLine(JsonObject poLine) { - poLine.remove(ALERTS); - poLine.remove(REPORTING_CODES); - return poLine.mapTo(CompositePoLine.class); + JsonObject poLineJson = JsonObject.mapFrom(poLine); + poLineJson.remove(ALERTS); + poLineJson.remove(REPORTING_CODES); + return poLineJson.mapTo(CompositePoLine.class); } public static PoLine convertToPoLine(CompositePoLine compPoLine) { From 276ea0370b6a6c367afaf4d213ded40eda63b762 Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Mon, 23 Sep 2024 14:01:42 +0400 Subject: [PATCH 09/11] [MODORDERS-1143] Fix future recovery issue --- src/main/java/org/folio/helper/PurchaseOrderLineHelper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index a85d7d6c2..6422d7cc8 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -590,11 +590,12 @@ private Future<List<Error>> validatePoLineLimit(CompositePoLine compPOL, JsonObj private Future<CompositePurchaseOrder> getCompositePurchaseOrder(String purchaseOrderId, RequestContext requestContext) { return purchaseOrderStorageService.getPurchaseOrderByIdAsJson(purchaseOrderId, requestContext) .map(HelperUtils::convertToCompositePurchaseOrder) - .onFailure(cause -> { + .recover(cause -> { // The case when specified order does not exist if (cause instanceof HttpException httpException && httpException.getCode() == Response.Status.NOT_FOUND.getStatusCode()) { throw new HttpException(422, ErrorCodes.ORDER_NOT_FOUND); } + throw new HttpException(500, cause.getMessage(), cause); }); } From 00adc164e9d626b41a645546f95d28e5e7425e87 Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Mon, 23 Sep 2024 14:15:52 +0400 Subject: [PATCH 10/11] [MODORDERS-1143] Fix sonar issues --- .../java/org/folio/helper/PurchaseOrderLineHelper.java | 5 ++--- src/main/java/org/folio/orders/utils/HelperUtils.java | 5 ----- .../java/org/folio/orders/utils/PoLineCommonUtil.java | 10 ++++------ .../folio/service/orders/OrderValidationService.java | 1 - .../pieces/flows/update/PieceUpdateFlowManager.java | 1 - 5 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java index 6422d7cc8..82a288865 100644 --- a/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java +++ b/src/main/java/org/folio/helper/PurchaseOrderLineHelper.java @@ -333,9 +333,8 @@ public Future<Void> updateOrderLine(CompositePoLine compOrderLine, JsonObject li return purchaseOrderLineService.updateSearchLocations(compOrderLine, requestContext) .compose(v -> purchaseOrderLineService.updatePoLineSubObjects(compOrderLine, lineFromStorage, requestContext)) .compose(poLine -> purchaseOrderLineService.updateOrderLineSummary(compOrderLine.getId(), poLine, requestContext)) - .onFailure(throwable -> { - logger.error("PoLine with id - '{}' partially updated but there are issues processing some PoLine sub-objects", compOrderLine.getId()); - }).mapEmpty(); + .onFailure(throwable -> logger.error("PoLine with id - '{}' partially updated but there are issues processing some PoLine sub-objects", compOrderLine.getId())) + .mapEmpty(); } public String buildNewPoLineNumber(PoLine poLineFromStorage, String poNumber) { diff --git a/src/main/java/org/folio/orders/utils/HelperUtils.java b/src/main/java/org/folio/orders/utils/HelperUtils.java index f3b4023f0..9566acbae 100644 --- a/src/main/java/org/folio/orders/utils/HelperUtils.java +++ b/src/main/java/org/folio/orders/utils/HelperUtils.java @@ -20,7 +20,6 @@ import org.folio.rest.core.exceptions.HttpException; import org.folio.rest.core.exceptions.NoInventoryRecordException; import org.folio.rest.core.models.RequestContext; -import org.folio.rest.jaxrs.model.Alert; import org.folio.rest.jaxrs.model.CompositePoLine; import org.folio.rest.jaxrs.model.CompositePurchaseOrder; import org.folio.rest.jaxrs.model.Cost; @@ -28,7 +27,6 @@ import org.folio.rest.jaxrs.model.Piece; import org.folio.rest.jaxrs.model.PoLine; import org.folio.rest.jaxrs.model.PurchaseOrder; -import org.folio.rest.jaxrs.model.ReportingCode; import org.folio.rest.jaxrs.model.Title; import org.folio.service.exchange.ExchangeRateProviderResolver; import org.javamoney.moneta.Money; @@ -55,12 +53,9 @@ import java.util.regex.Pattern; import static io.vertx.core.Future.succeededFuture; -import static java.util.stream.Collectors.toList; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.apache.commons.lang3.StringUtils.isEmpty; -import static org.folio.orders.utils.ResourcePathResolver.ALERTS; -import static org.folio.orders.utils.ResourcePathResolver.REPORTING_CODES; import static org.folio.rest.RestConstants.EN; import static org.folio.rest.core.exceptions.ErrorCodes.MULTIPLE_NONPACKAGE_TITLES; import static org.folio.rest.core.exceptions.ErrorCodes.TITLE_NOT_FOUND; diff --git a/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java b/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java index 694c55623..ad894a0c2 100644 --- a/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java +++ b/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java @@ -1,6 +1,5 @@ package org.folio.orders.utils; -import static java.util.stream.Collectors.toList; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.folio.orders.utils.HelperUtils.calculateTotalLocationQuantity; import static org.folio.orders.utils.ResourcePathResolver.ALERTS; @@ -266,16 +265,15 @@ public static PoLine convertToPoLine(CompositePoLine compPoLine) { pol.remove(ALERTS); pol.remove(REPORTING_CODES); PoLine poLine = pol.mapTo(PoLine.class); - poLine.setAlerts(compPoLine.getAlerts().stream().map(Alert::getId).collect(toList())); - poLine.setReportingCodes(compPoLine.getReportingCodes().stream().map(ReportingCode::getId).collect(toList())); + poLine.setAlerts(compPoLine.getAlerts().stream().map(Alert::getId).toList()); + poLine.setReportingCodes(compPoLine.getReportingCodes().stream().map(ReportingCode::getId).toList()); return poLine; } public static List<PoLine> convertToPoLines(List<CompositePoLine> compositePoLines) { - return compositePoLines - .stream() + return compositePoLines.stream() .map(PoLineCommonUtil::convertToPoLine) - .collect(toList()); + .toList(); } public static void updateLocationsQuantity(List<Location> locations) { diff --git a/src/main/java/org/folio/service/orders/OrderValidationService.java b/src/main/java/org/folio/service/orders/OrderValidationService.java index 805c14f43..2e0dd7b82 100644 --- a/src/main/java/org/folio/service/orders/OrderValidationService.java +++ b/src/main/java/org/folio/service/orders/OrderValidationService.java @@ -11,7 +11,6 @@ import org.folio.helper.PurchaseOrderLineHelper; import org.folio.okapi.common.GenericCompositeFuture; import org.folio.orders.utils.AcqDesiredPermissions; -import org.folio.orders.utils.HelperUtils; import org.folio.orders.utils.PoLineCommonUtil; import org.folio.orders.utils.ProtectedOperationType; import org.folio.rest.core.exceptions.ErrorCodes; diff --git a/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowManager.java b/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowManager.java index 952eac9f7..84da4a84c 100644 --- a/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowManager.java +++ b/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowManager.java @@ -15,7 +15,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.folio.models.pieces.PieceUpdateHolder; -import org.folio.orders.utils.HelperUtils; import org.folio.orders.utils.PoLineCommonUtil; import org.folio.rest.core.models.RequestContext; import org.folio.rest.jaxrs.model.CompositePoLine; From 2b49ada96fa404e35dd74c7562b662aae50d534b Mon Sep 17 00:00:00 2001 From: saba_zedginidze <saba_zedginidze@epam.com> Date: Mon, 23 Sep 2024 14:35:27 +0400 Subject: [PATCH 11/11] [MODORDERS-1143] Revert back to modifiable lists --- .../org/folio/orders/utils/PoLineCommonUtil.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java b/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java index ad894a0c2..b90d7a564 100644 --- a/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java +++ b/src/main/java/org/folio/orders/utils/PoLineCommonUtil.java @@ -1,5 +1,6 @@ package org.folio.orders.utils; +import static java.util.stream.Collectors.toList; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.folio.orders.utils.HelperUtils.calculateTotalLocationQuantity; import static org.folio.orders.utils.ResourcePathResolver.ALERTS; @@ -254,26 +255,26 @@ public static List<String> getTenantsFromLocations(List<Location> locations) { } public static CompositePoLine convertToCompositePoLine(PoLine poLine) { - JsonObject poLineJson = JsonObject.mapFrom(poLine); + var poLineJson = JsonObject.mapFrom(poLine); poLineJson.remove(ALERTS); poLineJson.remove(REPORTING_CODES); return poLineJson.mapTo(CompositePoLine.class); } public static PoLine convertToPoLine(CompositePoLine compPoLine) { - JsonObject pol = JsonObject.mapFrom(compPoLine); + var pol = JsonObject.mapFrom(compPoLine); pol.remove(ALERTS); pol.remove(REPORTING_CODES); - PoLine poLine = pol.mapTo(PoLine.class); - poLine.setAlerts(compPoLine.getAlerts().stream().map(Alert::getId).toList()); - poLine.setReportingCodes(compPoLine.getReportingCodes().stream().map(ReportingCode::getId).toList()); + var poLine = pol.mapTo(PoLine.class); + poLine.setAlerts(compPoLine.getAlerts().stream().map(Alert::getId).collect(toList())); + poLine.setReportingCodes(compPoLine.getReportingCodes().stream().map(ReportingCode::getId).collect(toList())); return poLine; } public static List<PoLine> convertToPoLines(List<CompositePoLine> compositePoLines) { return compositePoLines.stream() .map(PoLineCommonUtil::convertToPoLine) - .toList(); + .collect(toList()); } public static void updateLocationsQuantity(List<Location> locations) {