diff --git a/ramls/acq-models b/ramls/acq-models index 72dd1b15a..4aab2ae48 160000 --- a/ramls/acq-models +++ b/ramls/acq-models @@ -1 +1 @@ -Subproject commit 72dd1b15ae5b846d61d9ad14bb780ea233e01e38 +Subproject commit 4aab2ae4808333aac379cae40828dacdf0ef986c diff --git a/src/main/java/org/folio/orders/utils/HelperUtils.java b/src/main/java/org/folio/orders/utils/HelperUtils.java index b1d5885a7..2f09d0027 100644 --- a/src/main/java/org/folio/orders/utils/HelperUtils.java +++ b/src/main/java/org/folio/orders/utils/HelperUtils.java @@ -155,7 +155,7 @@ public static Integer calculateTotalLocationQuantity(Location location) { */ public static int calculateTotalQuantity(CompositePoLine compPOL) { Cost cost = compPOL.getCost(); - int eQuantity = ObjectUtils.defaultIfNull(cost.getQuantityElectronic(), 0); + int eQuantity = ObjectUtils.defaultIfNull(cost.getQuantityElectronic(), 0); int physicalQuantity = ObjectUtils.defaultIfNull(cost.getQuantityPhysical(), 0); return eQuantity + physicalQuantity; } @@ -177,7 +177,7 @@ public static int calculateInventoryItemsQuantity(CompositePoLine compPOL) { /** * Calculates items quantity for specified locations. * - * @param compPOL composite PO Line + * @param compPOL composite PO Line * @param locations list of locations to calculate quantity for * @return quantity of items expected in the inventory for PO Line * @see #calculateInventoryItemsQuantity(CompositePoLine) @@ -297,27 +297,25 @@ public static MonetaryAmount calculateEncumbranceEffectiveAmount(MonetaryAmount } public static int getPhysicalLocationsQuantity(List locations) { - if (CollectionUtils.isNotEmpty(locations)) { - return locations.stream() - .map(Location::getQuantityPhysical) - .filter(Objects::nonNull) - .mapToInt(Integer::intValue) - .sum(); - } else { + if (CollectionUtils.isEmpty(locations)) { return 0; } + return locations.stream() + .map(Location::getQuantityPhysical) + .filter(Objects::nonNull) + .mapToInt(Integer::intValue) + .sum(); } public static int getElectronicLocationsQuantity(List locations) { - if (CollectionUtils.isNotEmpty(locations)) { - return locations.stream() - .map(Location::getQuantityElectronic) - .filter(Objects::nonNull) - .mapToInt(Integer::intValue) - .sum(); - } else { + if (CollectionUtils.isEmpty(locations)) { return 0; } + return locations.stream() + .map(Location::getQuantityElectronic) + .filter(Objects::nonNull) + .mapToInt(Integer::intValue) + .sum(); } /** @@ -375,8 +373,6 @@ public static CompositePurchaseOrder convertToCompositePurchaseOrder(JsonObject } public static boolean changeOrderStatus(PurchaseOrder purchaseOrder, List poLines) { - boolean isUpdateRequired = false; - if (toBeCancelled(purchaseOrder, poLines)) { purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.CLOSED); purchaseOrder.setCloseReason(new CloseReason().withReason(REASON_CANCELLED)); @@ -384,14 +380,17 @@ public static boolean changeOrderStatus(PurchaseOrder purchaseOrder, List values, String fieldName, boolean strictMatch) { @@ -468,8 +467,7 @@ public static void verifyTitles(Map> lineIdTitles, Map> titles, Map poLineById) { - if (titles.keySet().stream().anyMatch(lineId -> titles.get(lineId).size() > 1 && - !poLineById.get(lineId).getIsPackage())) { + if (titles.keySet().stream().anyMatch(lineId -> titles.get(lineId).size() > 1 && !poLineById.get(lineId).getIsPackage())) { throw new HttpException(400, MULTIPLE_NONPACKAGE_TITLES); } } @@ -498,17 +496,17 @@ public static ConversionQuery getConversionQuery(Double exchangeRate, String fro } public static void makePoLinePending(CompositePoLine poLine) { - if (poLine.getPaymentStatus() == CompositePoLine.PaymentStatus.AWAITING_PAYMENT) { - poLine.setPaymentStatus(CompositePoLine.PaymentStatus.PENDING); - } - if (poLine.getReceiptStatus() == CompositePoLine.ReceiptStatus.AWAITING_RECEIPT) { - poLine.setReceiptStatus(CompositePoLine.ReceiptStatus.PENDING); - } + if (poLine.getPaymentStatus() == CompositePoLine.PaymentStatus.AWAITING_PAYMENT) { + poLine.setPaymentStatus(CompositePoLine.PaymentStatus.PENDING); + } + if (poLine.getReceiptStatus() == CompositePoLine.ReceiptStatus.AWAITING_RECEIPT) { + poLine.setReceiptStatus(CompositePoLine.ReceiptStatus.PENDING); + } } public static ConversionQuery buildConversionQuery(PoLine poLine, String systemCurrency) { Cost cost = poLine.getCost(); - if (cost.getExchangeRate() != null){ + if (cost.getExchangeRate() != null) { return ConversionQueryBuilder.of().setBaseCurrency(cost.getCurrency()) .setTermCurrency(systemCurrency) .set(RATE_KEY, cost.getExchangeRate()).build(); diff --git a/src/main/java/org/folio/service/inventory/InventoryManager.java b/src/main/java/org/folio/service/inventory/InventoryManager.java index 3bb87626a..71f211d9d 100644 --- a/src/main/java/org/folio/service/inventory/InventoryManager.java +++ b/src/main/java/org/folio/service/inventory/InventoryManager.java @@ -1268,15 +1268,28 @@ private Future> fetchHoldingsByFundIds(List holdingIds, }); } - private void updateItemWithPieceFields(Piece piece, JsonObject item) { - Optional.ofNullable(piece.getEnumeration()) - .ifPresentOrElse(enumeration -> item.put(ITEM_ENUMERATION, enumeration), () -> item.remove(ITEM_ENUMERATION)); - Optional.ofNullable(piece.getCopyNumber()) - .ifPresentOrElse(copyNumber -> item.put(COPY_NUMBER, copyNumber), () -> item.remove(COPY_NUMBER)); - Optional.ofNullable(piece.getChronology()) - .ifPresentOrElse(chronology -> item.put(ITEM_CHRONOLOGY, chronology), () -> item.remove(ITEM_CHRONOLOGY)); - Optional.ofNullable(piece.getDiscoverySuppress()) - .ifPresentOrElse(discSup -> item.put(ITEM_DISCOVERY_SUPPRESS, discSup), () -> item.remove(ITEM_DISCOVERY_SUPPRESS)); + void updateItemWithPieceFields(Piece piece, JsonObject item) { + if (StringUtils.isNotEmpty(piece.getEnumeration())) { + item.put(ITEM_ENUMERATION, piece.getEnumeration()); + } + if (StringUtils.isNotEmpty(piece.getCopyNumber())) { + item.put(COPY_NUMBER, piece.getCopyNumber()); + } + if (StringUtils.isNotEmpty(piece.getChronology())) { + item.put(ITEM_CHRONOLOGY, piece.getChronology()); + } + if (StringUtils.isNotEmpty(piece.getBarcode())) { + item.put(ITEM_BARCODE, piece.getBarcode()); + } + if (StringUtils.isNotEmpty(piece.getAccessionNumber())) { + item.put(ITEM_ACCESSION_NUMBER, piece.getAccessionNumber()); + } + if (StringUtils.isNotEmpty(piece.getCallNumber())) { + item.put(ITEM_LEVEL_CALL_NUMBER, piece.getCallNumber()); + } + if (piece.getDiscoverySuppress() != null) { + item.put(ITEM_DISCOVERY_SUPPRESS, piece.getDiscoverySuppress()); + } } public Future createShadowInstanceIfNeeded(String instanceId, RequestContext requestContext) { diff --git a/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowInventoryManager.java b/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowInventoryManager.java index fbd148c77..9f8b99fb0 100644 --- a/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowInventoryManager.java +++ b/src/main/java/org/folio/service/pieces/flows/update/PieceUpdateFlowInventoryManager.java @@ -3,7 +3,6 @@ import static org.folio.service.inventory.InventoryManager.ID; import static org.folio.service.inventory.InventoryManager.ITEM_HOLDINGS_RECORD_ID; import static org.folio.service.inventory.InventoryManager.ITEM_PURCHASE_ORDER_LINE_IDENTIFIER; -import static org.folio.service.inventory.InventoryManager.COPY_NUMBER; import java.util.Optional; @@ -45,9 +44,7 @@ public Future processInventory(PieceUpdateHolder holder, RequestContext re .compose(aVoid -> { if (Boolean.TRUE.equals(holder.getOriginPoLine().getIsPackage())) { return packagePoLineUpdateInventory(holder, requestContext); - } - else - { + } else { return nonPackagePoLineUpdateInventory(holder, requestContext); } }); @@ -93,15 +90,15 @@ private Future handleHolding(PieceUpdateHolder holder, RequestContext if (instanceId != null && DefaultPieceFlowsValidator.isCreateHoldingForPiecePossible(pieceToUpdate, poLineToSave)) { Location location = new Location().withLocationId(pieceToUpdate.getLocationId()); return inventoryManager.getOrCreateHoldingsRecord(instanceId, location, requestContext) - .map(holdingId -> { - Optional.ofNullable(holdingId).ifPresent(holdingIdP -> { - pieceToUpdate.setLocationId(null); - pieceToUpdate.setHoldingId(holdingId); - location.setLocationId(null); - location.setHoldingId(holdingId); - }); - return location; - }); + .map(holdingId -> { + Optional.ofNullable(holdingId).ifPresent(holdingIdP -> { + pieceToUpdate.setLocationId(null); + pieceToUpdate.setHoldingId(holdingId); + location.setLocationId(null); + location.setHoldingId(holdingId); + }); + return location; + }); } return Future.succeededFuture(new Location().withLocationId(pieceToUpdate.getLocationId())); } @@ -109,27 +106,26 @@ private Future handleHolding(PieceUpdateHolder holder, RequestContext private Future handleItem(PieceUpdateHolder holder, RequestContext requestContext) { CompositePoLine poLineToSave = holder.getPoLineToSave(); Piece pieceToUpdate = holder.getPieceToUpdate(); - if (DefaultPieceFlowsValidator.isCreateItemForPiecePossible(pieceToUpdate, poLineToSave)) { - return inventoryManager.getItemRecordById(pieceToUpdate.getItemId(), true, requestContext) - .compose(jsonItem -> { - if (holder.isCreateItem() && (jsonItem == null || jsonItem.isEmpty()) && pieceToUpdate.getHoldingId() != null) { + if (!DefaultPieceFlowsValidator.isCreateItemForPiecePossible(pieceToUpdate, poLineToSave)) { + return Future.succeededFuture(); + } + return inventoryManager.getItemRecordById(pieceToUpdate.getItemId(), true, requestContext) + .compose(jsonItem -> { + boolean jsonItemFound = jsonItem != null && !jsonItem.isEmpty(); + if (holder.isCreateItem() && !jsonItemFound && pieceToUpdate.getHoldingId() != null) { return pieceUpdateInventoryService.manualPieceFlowCreateItemRecord(pieceToUpdate, poLineToSave, requestContext); - } else if (jsonItem != null && !jsonItem.isEmpty()) { - return updateItemWithFields(jsonItem, poLineToSave, pieceToUpdate).compose( - aVoid -> inventoryManager.updateItem(jsonItem, requestContext).map(item -> jsonItem.getString(ID))); - } else { - return Future.succeededFuture(); } + if (jsonItemFound) { + return updateItemWithFields(jsonItem, poLineToSave, pieceToUpdate) + .compose(ignored -> inventoryManager.updateItem(jsonItem, requestContext).map(item -> jsonItem.getString(ID))); + } + return Future.succeededFuture(); }); - } - return Future.succeededFuture(); } private Future updateItemWithFields(JsonObject item, CompositePoLine compPOL, Piece piece) { Optional.ofNullable(piece.getHoldingId()) .ifPresent(pieceHoldingId -> item.put(ITEM_HOLDINGS_RECORD_ID, piece.getHoldingId())); - Optional.ofNullable(piece.getCopyNumber()) - .ifPresentOrElse(copyNumber -> item.put(COPY_NUMBER, copyNumber), () -> item.remove(COPY_NUMBER)); item.put(ITEM_PURCHASE_ORDER_LINE_IDENTIFIER, compPOL.getId()); return Future.succeededFuture(); } @@ -137,28 +133,27 @@ private Future updateItemWithFields(JsonObject item, CompositePoLine compP private Future nonPackageUpdateTitleWithInstance(PieceUpdateHolder holder, RequestContext requestContext) { CompositePoLine poLineToSave = holder.getPoLineToSave(); Piece pieceToUpdate = holder.getPieceToUpdate(); - if (poLineToSave.getInstanceId() == null && !PoLineCommonUtil.isInventoryUpdateNotRequired(poLineToSave)) { - return titlesService.getTitleById(pieceToUpdate.getTitleId(), requestContext) - .compose(title -> { - if (title.getInstanceId() == null) { - return createTitleInstance(title, requestContext); - } - return Future.succeededFuture(title.getInstanceId()); - }) - .map(instanceId -> poLineToSave.withInstanceId(instanceId).getInstanceId()); + if (poLineToSave.getInstanceId() != null || PoLineCommonUtil.isInventoryUpdateNotRequired(poLineToSave)) { + return Future.succeededFuture(poLineToSave.getInstanceId()); } - return Future.succeededFuture(poLineToSave.getInstanceId()); + return titlesService.getTitleById(pieceToUpdate.getTitleId(), requestContext) + .compose(title -> { + if (title.getInstanceId() == null) { + return createTitleInstance(title, requestContext); + } + return Future.succeededFuture(title.getInstanceId()); + }) + .map(instanceId -> poLineToSave.withInstanceId(instanceId).getInstanceId()); } private Future packageUpdateTitleWithInstance(Title title, RequestContext requestContext) { if (title.getInstanceId() != null) { return Future.succeededFuture(title); - } else { - return inventoryManager.getOrCreateInstanceRecord(title, requestContext) - .map(title::withInstanceId) - .compose(titleWithInstanceId -> titlesService.saveTitle(titleWithInstanceId, requestContext)) - .map(v -> title); } + return inventoryManager.getOrCreateInstanceRecord(title, requestContext) + .map(title::withInstanceId) + .compose(titleWithInstanceId -> titlesService.saveTitle(titleWithInstanceId, requestContext)) + .map(v -> title); } private Future<String> createTitleInstance(Title title, RequestContext requestContext) { diff --git a/src/test/java/org/folio/service/inventory/InventoryManagerTest.java b/src/test/java/org/folio/service/inventory/InventoryManagerTest.java index 4f3f3e2c2..7cd07610a 100644 --- a/src/test/java/org/folio/service/inventory/InventoryManagerTest.java +++ b/src/test/java/org/folio/service/inventory/InventoryManagerTest.java @@ -29,16 +29,24 @@ import static org.folio.rest.impl.PurchaseOrderLinesApiTest.COMP_PO_LINES_MOCK_DATA_PATH; import static org.folio.rest.impl.PurchaseOrdersApiTest.X_OKAPI_TENANT; import static org.folio.rest.jaxrs.model.Eresource.CreateInventory.INSTANCE_HOLDING; +import static org.folio.service.inventory.InventoryManager.COPY_NUMBER; import static org.folio.service.inventory.InventoryManager.HOLDINGS_RECORDS; import static org.folio.service.inventory.InventoryManager.HOLDINGS_SOURCES; import static org.folio.service.inventory.InventoryManager.HOLDING_PERMANENT_LOCATION_ID; import static org.folio.service.inventory.InventoryManager.ID; import static org.folio.service.inventory.InventoryManager.ITEMS; +import static org.folio.service.inventory.InventoryManager.ITEM_ACCESSION_NUMBER; +import static org.folio.service.inventory.InventoryManager.ITEM_BARCODE; +import static org.folio.service.inventory.InventoryManager.ITEM_CHRONOLOGY; +import static org.folio.service.inventory.InventoryManager.ITEM_DISCOVERY_SUPPRESS; +import static org.folio.service.inventory.InventoryManager.ITEM_ENUMERATION; +import static org.folio.service.inventory.InventoryManager.ITEM_LEVEL_CALL_NUMBER; import static org.folio.service.inventory.InventoryManager.ITEM_PURCHASE_ORDER_LINE_IDENTIFIER; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -492,6 +500,71 @@ void testShouldBuildInstanceWithFieldFromTitles() { verify(title).getProductIds(); } + @Test + void testUpdateItemWithPieceFields() { + // given + Piece piece = new Piece(); + piece.setEnumeration("enumeration"); + piece.setCopyNumber("copy number"); + piece.setChronology("chronology"); + piece.setBarcode("barcode"); + piece.setAccessionNumber("accession number"); + piece.setCallNumber("call number"); + piece.setDiscoverySuppress(true); + + String oldValue = "old value"; + JsonObject item = new JsonObject(new HashMap<>(Map.of( + ITEM_ENUMERATION, oldValue, + COPY_NUMBER, oldValue, + ITEM_CHRONOLOGY, oldValue, + ITEM_BARCODE, oldValue, + ITEM_ACCESSION_NUMBER, oldValue, + ITEM_LEVEL_CALL_NUMBER, oldValue, + ITEM_DISCOVERY_SUPPRESS, false + ))); + + // when + inventoryManager.updateItemWithPieceFields(piece, item); + + // then + assertEquals(piece.getEnumeration(), item.getString(ITEM_ENUMERATION)); + assertEquals(piece.getCopyNumber(), item.getString(COPY_NUMBER)); + assertEquals(piece.getChronology(), item.getString(ITEM_CHRONOLOGY)); + assertEquals(piece.getBarcode(), item.getString(ITEM_BARCODE)); + assertEquals(piece.getAccessionNumber(), item.getString(ITEM_ACCESSION_NUMBER)); + assertEquals(piece.getCallNumber(), item.getString(ITEM_LEVEL_CALL_NUMBER)); + assertEquals(piece.getDiscoverySuppress(), item.getBoolean(ITEM_DISCOVERY_SUPPRESS)); + } + + @Test + void testUpdateItemWithPieceFields_notOverwrite() { + // given + Piece piece = new Piece(); + + String oldValue = "old value"; + JsonObject item = new JsonObject(new HashMap<>(Map.of( + ITEM_ENUMERATION, oldValue, + COPY_NUMBER, oldValue, + ITEM_CHRONOLOGY, oldValue, + ITEM_BARCODE, oldValue, + ITEM_ACCESSION_NUMBER, oldValue, + ITEM_LEVEL_CALL_NUMBER, oldValue, + ITEM_DISCOVERY_SUPPRESS, false + ))); + + // when + inventoryManager.updateItemWithPieceFields(piece, item); + + // then + assertEquals(oldValue, item.getString(ITEM_ENUMERATION)); + assertEquals(oldValue, item.getString(COPY_NUMBER)); + assertEquals(oldValue, item.getString(ITEM_CHRONOLOGY)); + assertEquals(oldValue, item.getString(ITEM_BARCODE)); + assertEquals(oldValue, item.getString(ITEM_ACCESSION_NUMBER)); + assertEquals(oldValue, item.getString(ITEM_LEVEL_CALL_NUMBER)); + assertFalse(item.getBoolean(ITEM_DISCOVERY_SUPPRESS)); + } + @Test void shouldCheckIfTheHoldingExistsWhenHoldingIdSpecifiedAndIfExistThenReturnHoldingIdFromLocation() throws IOException { String instanceId = UUID.randomUUID().toString();