Skip to content

Commit

Permalink
MODTLR-98 Fix existing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
OleksandrVidinieiev committed Dec 6, 2024
1 parent 2c930aa commit 311c681
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 260 deletions.
2 changes: 0 additions & 2 deletions src/main/java/org/folio/service/RequestService.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ CirculationItem updateCirculationItemOnRequestCreation(CirculationItem circulati
Request secondaryRequest);

InventoryItem getItemFromStorage(String itemId, String tenantId);

InventoryInstance getInstanceFromStorage(String instanceId, String tenantId);

Request getRequestFromStorage(String requestId, String tenantId);
Request getRequestFromStorage(String requestId);
Collection<Request> getRequestsFromStorage(CqlQuery query, String idIndex, Collection<String> ids);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/folio/service/impl/EcsTlrServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import java.util.stream.Collectors;

import org.folio.domain.RequestWrapper;
import org.folio.domain.dto.CirculationItem;
import org.folio.domain.dto.EcsTlr;
import org.folio.domain.dto.Request;
import org.folio.domain.entity.EcsTlrEntity;
Expand All @@ -20,6 +19,7 @@
import org.folio.service.EcsTlrService;
import org.folio.service.RequestService;
import org.folio.service.TenantService;
import org.folio.service.UserTenantsService;
import org.springframework.stereotype.Service;

import lombok.RequiredArgsConstructor;
Expand All @@ -35,7 +35,7 @@ public class EcsTlrServiceImpl implements EcsTlrService {
private final TenantService tenantService;
private final RequestService requestService;
private final DcbService dcbService;
private final UserTenantsServiceImpl userTenantsService;
private final UserTenantsService userTenantsService;

@Override
public Optional<EcsTlr> get(UUID id) {
Expand Down
257 changes: 8 additions & 249 deletions src/main/java/org/folio/service/impl/LoanEventHandler.java
Original file line number Diff line number Diff line change
@@ -1,37 +1,13 @@
package org.folio.service.impl;

import static org.folio.domain.dto.Request.EcsRequestPhaseEnum.PRIMARY;
import static org.folio.domain.dto.Request.EcsRequestPhaseEnum.SECONDARY;
import static org.folio.domain.dto.TransactionStatus.StatusEnum.AWAITING_PICKUP;
import static org.folio.domain.dto.TransactionStatus.StatusEnum.CANCELLED;
import static org.folio.domain.dto.TransactionStatus.StatusEnum.ITEM_CHECKED_OUT;
import static org.folio.domain.dto.TransactionStatus.StatusEnum.OPEN;
import static org.folio.support.KafkaEvent.EventType.CREATED;
import static org.folio.support.KafkaEvent.EventType.UPDATED;

import java.util.Date;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;

import org.folio.domain.dto.Loan;
import org.folio.domain.dto.Request;
import org.folio.domain.dto.Request.EcsRequestPhaseEnum;
import org.folio.domain.dto.Request.FulfillmentPreferenceEnum;
import org.folio.domain.dto.ServicePoint;
import org.folio.domain.dto.TransactionStatus;
import org.folio.domain.entity.EcsTlrEntity;
import org.folio.repository.EcsTlrRepository;
import org.folio.service.CloningService;
import org.folio.service.DcbService;
import org.folio.service.KafkaEventHandler;
import org.folio.service.RequestService;
import org.folio.service.ServicePointService;
import org.folio.spring.service.SystemUserScopedExecutionService;
import org.folio.support.KafkaEvent;
import org.springframework.stereotype.Service;

import feign.FeignException;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;

Expand All @@ -40,242 +16,25 @@
@Log4j2
public class LoanEventHandler implements KafkaEventHandler<Loan> {

private final DcbService dcbService;
private final EcsTlrRepository ecsTlrRepository;
private final SystemUserScopedExecutionService executionService;
private final ServicePointService servicePointService;
private final CloningService<ServicePoint> servicePointCloningService;
private final RequestService requestService;

@Override
public void handle(KafkaEvent<Loan> event) {
log.info("handle:: processing loan event: {}", event::getId);
if (event.getType() == UPDATED) {
if (event.getType() == CREATED) {
handleLoanCreationEvent(event);
} else if (event.getType() == UPDATED) {
handleLoanUpdateEvent(event);
} else {
log.info("handle:: ignoring event {} of unsupported type: {}", event::getId, event::getType);
}
log.info("handle:: loan event processed: {}", event::getId);
}

private void handleLoanUpdateEvent(KafkaEvent<Loan> event) {
log.info("handleLoanUpdateEvent:: handling loan update event: {}", event::getId);
// Loan updatedRequest = event.getData().getNewVersion();
// if (updatedRequest == null) {
// log.warn("handleRequestUpdateEvent:: event does not contain new version of request");
// return;
// }
// if (updatedRequest.getEcsRequestPhase() == null) {
// log.info("handleRequestUpdateEvent:: updated request is not an ECS request");
// return;
// }
// if (updatedRequest.getEcsRequestPhase() == SECONDARY && updatedRequest.getItemId() == null) {
// log.info("handleRequestUpdateEvent:: updated secondary request does not contain itemId");
// return;
// }
// String requestId = updatedRequest.getId();
// log.info("handleRequestUpdateEvent:: looking for ECS TLR for request {}", requestId);
// // we can search by either primary or secondary request ID, they are identical
// ecsTlrRepository.findBySecondaryRequestId(UUID.fromString(requestId)).ifPresentOrElse(
// ecsTlr -> handleRequestUpdateEvent(ecsTlr, event),
// () -> log.info("handleSecondaryRequestUpdate: ECS TLR for request {} not found", requestId));
}

private void handleRequestUpdateEvent(EcsTlrEntity ecsTlr, KafkaEvent<Request> event) {
log.debug("handleRequestUpdateEvent:: ecsTlr={}", () -> ecsTlr);
Request updatedRequest = event.getData().getNewVersion();

if (!requestMatchesEcsTlr(ecsTlr, updatedRequest, event.getTenantIdHeaderValue())) {
return;
}
if (updatedRequest.getEcsRequestPhase() == PRIMARY) {
handlePrimaryRequestUpdate(ecsTlr, event);
}
if (updatedRequest.getEcsRequestPhase() == SECONDARY) {
handleSecondaryRequestUpdate(ecsTlr, event);
}
}

private static boolean requestMatchesEcsTlr(EcsTlrEntity ecsTlr, Request updatedRequest,
String updatedRequestTenant) {

final EcsRequestPhaseEnum updatedRequestPhase = updatedRequest.getEcsRequestPhase();
final UUID updatedRequestId = UUID.fromString(updatedRequest.getId());

if (updatedRequestPhase == PRIMARY && updatedRequestId.equals(ecsTlr.getPrimaryRequestId())
&& updatedRequestTenant.equals(ecsTlr.getPrimaryRequestTenantId())) {
log.info("requestMatchesEcsTlr:: updated primary request matches ECS TLR");
return true;
} else if (updatedRequestPhase == SECONDARY && updatedRequestId.equals(ecsTlr.getSecondaryRequestId())
&& updatedRequestTenant.equals(ecsTlr.getSecondaryRequestTenantId())) {
log.info("requestMatchesEcsTlr:: updated secondary request matches ECS TLR");
return true;
}
log.warn("requestMatchesEcsTlr:: request does not match ECS TLR: updatedRequestPhase={}, " +
"updatedRequestId={}, updatedRequestTenant={}, ecsTlr={}", updatedRequestPhase,
updatedRequestId, updatedRequestTenant, ecsTlr);
return false;
private void handleLoanCreationEvent(KafkaEvent<Loan> event) {
log.info("handleLoanUpdateEvent:: handling loan creation event: {}", event::getId);
}

private void handlePrimaryRequestUpdate(EcsTlrEntity ecsTlr, KafkaEvent<Request> event) {
propagateChangesFromPrimaryToSecondaryRequest(ecsTlr, event);
updateTransactionStatuses(event, ecsTlr);
}

private void handleSecondaryRequestUpdate(EcsTlrEntity ecsTlr, KafkaEvent<Request> event) {
processItemIdUpdate(ecsTlr, event.getData().getNewVersion());
updateTransactionStatuses(event, ecsTlr);
}

private void processItemIdUpdate(EcsTlrEntity ecsTlr, Request updatedRequest) {
if (ecsTlr.getItemId() != null) {
log.info("processItemIdUpdate:: ECS TLR {} already has itemId {}", ecsTlr::getId, ecsTlr::getItemId);
return;
}
log.info("processItemIdUpdate:: updating ECS TLR {} with itemId {}", ecsTlr::getId,
updatedRequest::getItemId);
ecsTlr.setItemId(UUID.fromString(updatedRequest.getItemId()));
// TODO: change this if Page request works
dcbService.createTransactions(ecsTlr, updatedRequest);
ecsTlrRepository.save(ecsTlr);
log.info("processItemIdUpdate: ECS TLR {} is updated", ecsTlr::getId);
}

private static Optional<TransactionStatus.StatusEnum> determineNewTransactionStatus(
KafkaEvent<Request> event) {

final Request.StatusEnum oldRequestStatus = event.getData().getOldVersion().getStatus();
final Request.StatusEnum newRequestStatus = event.getData().getNewVersion().getStatus();
log.info("determineNewTransactionStatus:: oldRequestStatus='{}', newRequestStatus='{}'",
oldRequestStatus, newRequestStatus);

if (newRequestStatus == oldRequestStatus) {
log.info("determineNewTransactionStatus:: request status did not change");
return Optional.empty();
}

var newTransactionStatus = Optional.ofNullable(
switch (newRequestStatus) {
case OPEN_IN_TRANSIT -> OPEN;
case OPEN_AWAITING_PICKUP -> AWAITING_PICKUP;
case CLOSED_FILLED -> ITEM_CHECKED_OUT;
case CLOSED_CANCELLED -> CANCELLED;
default -> null;
});

newTransactionStatus.ifPresentOrElse(
ts -> log.info("determineNewTransactionStatus:: new transaction status: {}", ts),
() -> log.info("determineNewTransactionStatus:: irrelevant request status change"));

return newTransactionStatus;
}

private void updateTransactionStatuses(KafkaEvent<Request> event, EcsTlrEntity ecsTlr) {
determineNewTransactionStatus(event)
.ifPresent(newStatus -> updateTransactionStatuses(newStatus, ecsTlr));
}

private void updateTransactionStatuses(TransactionStatus.StatusEnum newStatus, EcsTlrEntity ecsTlr) {
log.info("updateTransactionStatuses:: updating primary transaction status to {}", newStatus::getValue);
updateTransactionStatus(ecsTlr.getPrimaryRequestDcbTransactionId(), newStatus,
ecsTlr.getPrimaryRequestTenantId());

log.info("updateTransactionStatuses:: updating intermediate transaction status to {}", newStatus::getValue);
updateTransactionStatus(ecsTlr.getIntermediateRequestDcbTransactionId(), newStatus,
ecsTlr.getIntermediateRequestTenantId());

log.info("updateTransactionStatuses:: updating secondary transaction status to {}", newStatus::getValue);
updateTransactionStatus(ecsTlr.getSecondaryRequestDcbTransactionId(), newStatus,
ecsTlr.getSecondaryRequestTenantId());
}

private void updateTransactionStatus(UUID transactionId,
TransactionStatus.StatusEnum newStatus, String tenantId) {

if (transactionId == null) {
log.info("updateTransactionStatus:: transaction ID is null, doing nothing");
return;
}
if (tenantId == null) {
log.info("updateTransactionStatus:: tenant ID is null, doing nothing");
return;
}

try {
var currentStatus = dcbService.getTransactionStatus(transactionId, tenantId).getStatus();
log.info("updateTransactionStatus:: current transaction status: {}", currentStatus);
if (newStatus.getValue().equals(currentStatus.getValue())) {
log.info("updateTransactionStatus:: transaction status did not change, doing nothing");
return;
}
log.info("updateTransactionStatus: changing status of transaction {} in tenant {} from {} to {}",
transactionId, tenantId, currentStatus.getValue(), newStatus.getValue());
dcbService.updateTransactionStatus(transactionId, newStatus, tenantId);
} catch (FeignException.NotFound e) {
log.error("updateTransactionStatus:: transaction {} not found: {}", transactionId, e.getMessage());
} catch (Exception e) {
log.error("updateTransactionStatus:: failed to update transaction status: {}", e::getMessage);
log.debug("updateTransactionStatus:: ", e);
}
}

private void propagateChangesFromPrimaryToSecondaryRequest(EcsTlrEntity ecsTlr,
KafkaEvent<Request> event) {

String secondaryRequestId = ecsTlr.getSecondaryRequestId().toString();
String secondaryRequestTenantId = ecsTlr.getSecondaryRequestTenantId();
Request primaryRequest = event.getData().getNewVersion();
Request secondaryRequest = requestService.getRequestFromStorage(
secondaryRequestId, secondaryRequestTenantId);

boolean shouldUpdateSecondaryRequest = false;
if (valueIsNotEqual(primaryRequest, secondaryRequest, Request::getRequestExpirationDate)) {
Date requestExpirationDate = primaryRequest.getRequestExpirationDate();
log.info("propagateChangesFromPrimaryToSecondaryRequest:: request expiration date changed: {}",
requestExpirationDate);
secondaryRequest.setRequestExpirationDate(requestExpirationDate);
shouldUpdateSecondaryRequest = true;
}
if (valueIsNotEqual(primaryRequest, secondaryRequest, Request::getFulfillmentPreference)) {
FulfillmentPreferenceEnum fulfillmentPreference = primaryRequest.getFulfillmentPreference();
log.info("propagateChangesFromPrimaryToSecondaryRequest:: fulfillment preference changed: {}",
fulfillmentPreference);
secondaryRequest.setFulfillmentPreference(fulfillmentPreference);
shouldUpdateSecondaryRequest = true;
}
if (valueIsNotEqual(primaryRequest, secondaryRequest, Request::getPickupServicePointId)) {
String pickupServicePointId = primaryRequest.getPickupServicePointId();
log.info("propagateChangesFromPrimaryToSecondaryRequest:: pickup service point ID changed: {}",
pickupServicePointId);
secondaryRequest.setPickupServicePointId(pickupServicePointId);
shouldUpdateSecondaryRequest = true;
clonePickupServicePoint(ecsTlr, pickupServicePointId);
}

if (!shouldUpdateSecondaryRequest) {
log.info("propagateChangesFromPrimaryToSecondaryRequest:: no relevant changes detected");
return;
}

log.info("propagateChangesFromPrimaryToSecondaryRequest:: updating secondary request");
requestService.updateRequestInStorage(secondaryRequest, secondaryRequestTenantId);
log.info("propagateChangesFromPrimaryToSecondaryRequest:: secondary request updated");
}

private void clonePickupServicePoint(EcsTlrEntity ecsTlr, String pickupServicePointId) {
if (pickupServicePointId == null) {
log.info("clonePickupServicePoint:: pickupServicePointId is null, doing nothing");
return;
}
log.info("clonePickupServicePoint:: ensuring that service point {} exists in lending tenant",
pickupServicePointId);
ServicePoint pickupServicePoint = executionService.executeSystemUserScoped(
ecsTlr.getPrimaryRequestTenantId(), () -> servicePointService.find(pickupServicePointId));
executionService.executeSystemUserScoped(ecsTlr.getSecondaryRequestTenantId(),
() -> servicePointCloningService.clone(pickupServicePoint));
private void handleLoanUpdateEvent(KafkaEvent<Loan> event) {
log.info("handleLoanUpdateEvent:: handling loan update event: {}", event::getId);
}

private static <T, V> boolean valueIsNotEqual(T o1, T o2, Function<T, V> valueExtractor) {
return !Objects.equals(valueExtractor.apply(o1), valueExtractor.apply(o2));
}
}
3 changes: 0 additions & 3 deletions src/main/java/org/folio/service/impl/RequestServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.folio.domain.dto.User;
import org.folio.exception.RequestCreatingException;
import org.folio.service.CloningService;
import org.folio.service.ConsortiaService;
import org.folio.service.RequestService;
import org.folio.service.ServicePointService;
import org.folio.service.UserService;
Expand Down Expand Up @@ -54,8 +53,6 @@ public class RequestServiceImpl implements RequestService {
private final ServicePointService servicePointService;
private final CloningService<User> userCloningService;
private final CloningService<ServicePoint> servicePointCloningService;
private final ConsortiaService consortiaService;
private final UserTenantsServiceImpl userTenantsService;
private final SystemUserScopedExecutionService systemUserScopedExecutionService;

public static final String HOLDINGS_RECORD_ID = "10cd3a5a-d36f-4c7a-bc4f-e1ae3cf820c9";
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/org/folio/api/EcsTlrApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ void ecsTlrIsCreated(RequestTypeEnum requestType, boolean secondaryRequestReques
// 1.5 Mock DCB endpoints

DcbTransaction borrowerTransactionPostRequest = new DcbTransaction()
.role(DcbTransaction.RoleEnum.BORROWER)
.role(DcbTransaction.RoleEnum.BORROWING_PICKUP)
.item(new DcbItem()
.id(ITEM_ID)
.barcode(ITEM_BARCODE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ private static void verifyThatDcbTransactionsWereCreated(EcsTlrEntity ecsTlr) {
assertNotNull(secondaryRequestDcbTransactionId);

DcbTransaction expectedBorrowerTransaction = new DcbTransaction()
.role(DcbTransaction.RoleEnum.BORROWER)
.role(DcbTransaction.RoleEnum.BORROWING_PICKUP)
.item(new DcbItem()
.id(ecsTlr.getItemId().toString())
.barcode("test")
Expand Down
7 changes: 5 additions & 2 deletions src/test/java/org/folio/service/EcsTlrServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class EcsTlrServiceTest {
private TenantService tenantService;
@Mock
private DcbService dcbService;
@Mock
private UserTenantsService userTenantsService;
@Spy
private final EcsTlrMapper ecsTlrMapper = new EcsTlrMapperImpl();

Expand Down Expand Up @@ -99,6 +101,7 @@ void ecsTlrShouldBeCreatedThenUpdatedAndDeleted(EcsTlr.RequestLevelEnum requestL
.id(UUID.randomUUID().toString())
.itemId(UUID.randomUUID().toString());

when(userTenantsService.getCentralTenantId()).thenReturn(borrowingTenant);
when(ecsTlrRepository.save(any(EcsTlrEntity.class))).thenReturn(mockEcsTlrEntity);
when(tenantService.getPrimaryRequestTenantId(any(EcsTlrEntity.class)))
.thenReturn(borrowingTenant);
Expand Down Expand Up @@ -140,7 +143,7 @@ void canNotCreateEcsTlrWhenFailedToGetBorrowingTenantId() {
TenantPickingException exception = assertThrows(TenantPickingException.class,
() -> ecsTlrService.create(ecsTlr));

assertEquals("Failed to get borrowing tenant", exception.getMessage());
assertEquals("Failed to get primary request tenant", exception.getMessage());
}

@Test
Expand All @@ -155,6 +158,6 @@ void canNotCreateEcsTlrWhenFailedToGetLendingTenants() {
TenantPickingException exception = assertThrows(TenantPickingException.class,
() -> ecsTlrService.create(ecsTlr));

assertEquals("Failed to find lending tenants for instance " + instanceId, exception.getMessage());
assertEquals("Failed to find secondary request tenants for instance " + instanceId, exception.getMessage());
}
}

0 comments on commit 311c681

Please sign in to comment.