Skip to content

Commit

Permalink
Modorders 970 (#817)
Browse files Browse the repository at this point in the history
[MODORDERS-970] - Do not overwrite Item fields when piece fields are null/empty
  • Loading branch information
imerabishvili authored Jan 15, 2024
1 parent f876c51 commit cbe8a8a
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 82 deletions.
60 changes: 29 additions & 31 deletions src/main/java/org/folio/orders/utils/HelperUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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)
Expand Down Expand Up @@ -297,27 +297,25 @@ public static MonetaryAmount calculateEncumbranceEffectiveAmount(MonetaryAmount
}

public static int getPhysicalLocationsQuantity(List<Location> 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<Location> 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();
}

/**
Expand Down Expand Up @@ -375,23 +373,24 @@ public static CompositePurchaseOrder convertToCompositePurchaseOrder(JsonObject
}

public static boolean changeOrderStatus(PurchaseOrder purchaseOrder, List<PoLine> poLines) {
boolean isUpdateRequired = false;

if (toBeCancelled(purchaseOrder, poLines)) {
purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.CLOSED);
purchaseOrder.setCloseReason(new CloseReason().withReason(REASON_CANCELLED));
return true;
}

if (toBeClosed(purchaseOrder, poLines)) {
isUpdateRequired = true;
purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.CLOSED);
purchaseOrder.setCloseReason(new CloseReason().withReason(REASON_COMPLETE));
} else if (toBeReopened(purchaseOrder, poLines)) {
isUpdateRequired = true;
return true;
}

if (toBeReopened(purchaseOrder, poLines)) {
purchaseOrder.setWorkflowStatus(PurchaseOrder.WorkflowStatus.OPEN);
return true;
}
return isUpdateRequired;

return false;
}

public static String convertTagListToCqlQuery(Collection<String> values, String fieldName, boolean strictMatch) {
Expand Down Expand Up @@ -468,8 +467,7 @@ public static void verifyTitles(Map<String, List<Title>> lineIdTitles, Map<Strin

private static void verifyNonPackageLinesHaveSingleTitle(Map<String, List<Title>> titles,
Map<String, CompositePoLine> 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);
}
}
Expand Down Expand Up @@ -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();
Expand Down
31 changes: 22 additions & 9 deletions src/main/java/org/folio/service/inventory/InventoryManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -1268,15 +1268,28 @@ private Future<List<JsonObject>> fetchHoldingsByFundIds(List<String> 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<SharingInstance> createShadowInstanceIfNeeded(String instanceId, RequestContext requestContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -45,9 +44,7 @@ public Future<Void> processInventory(PieceUpdateHolder holder, RequestContext re
.compose(aVoid -> {
if (Boolean.TRUE.equals(holder.getOriginPoLine().getIsPackage())) {
return packagePoLineUpdateInventory(holder, requestContext);
}
else
{
} else {
return nonPackagePoLineUpdateInventory(holder, requestContext);
}
});
Expand Down Expand Up @@ -93,72 +90,70 @@ private Future<Location> 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()));
}

private Future<String> 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<Void> 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();
}

private Future<String> 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<Title> 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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit cbe8a8a

Please sign in to comment.