diff --git a/src/main/java/org/folio/dcb/listener/kafka/CirculationEventListener.java b/src/main/java/org/folio/dcb/listener/kafka/CirculationEventListener.java index 49069a2a..839f0dc6 100644 --- a/src/main/java/org/folio/dcb/listener/kafka/CirculationEventListener.java +++ b/src/main/java/org/folio/dcb/listener/kafka/CirculationEventListener.java @@ -17,6 +17,7 @@ import static org.folio.dcb.domain.dto.DcbTransaction.RoleEnum.BORROWING_PICKUP; import static org.folio.dcb.domain.dto.DcbTransaction.RoleEnum.LENDER; import static org.folio.dcb.domain.dto.DcbTransaction.RoleEnum.PICKUP; +import static org.folio.dcb.utils.DCBConstants.ITEM_UNAVAILABLE_CANCELLATION_MSG; import static org.folio.dcb.utils.TransactionHelper.getHeaderValue; import static org.folio.dcb.utils.TransactionHelper.parseLoanEvent; import static org.folio.dcb.utils.TransactionHelper.parseRequestEvent; @@ -78,14 +79,15 @@ public void handleRequestEvent(String data, MessageHeaders messageHeaders) { systemUserScopedExecutionService.executeAsyncSystemUserScoped(tenantId, () -> transactionRepository.findTransactionByRequestIdAndStatusNotInClosed(UUID.fromString(requestId)) .ifPresent(transactionEntity -> { - if (eventData.getType() == EventData.EventType.CANCEL) { + if (eventData.getType() == EventData.EventType.CANCEL && + !ITEM_UNAVAILABLE_CANCELLATION_MSG.equals(eventData.getCancellationAdditionalInformation())) { baseLibraryService.cancelTransactionEntity(transactionEntity); } else if (eventData.getType() == EventData.EventType.IN_TRANSIT && transactionEntity.getRole() == LENDER) { baseLibraryService.updateTransactionEntity(transactionEntity, TransactionStatus.StatusEnum.OPEN); } else if (eventData.getType() == EventData.EventType.AWAITING_PICKUP && (transactionEntity.getRole() == BORROWING_PICKUP || transactionEntity.getRole() == PICKUP)) { baseLibraryService.updateTransactionEntity(transactionEntity, TransactionStatus.StatusEnum.AWAITING_PICKUP); } else { - log.info("handleRequestEvent:: status for event {} can not be updated", eventData.getType()); + log.info("handleRequestEvent:: status for event {} can not be updated", eventData); } }) ); diff --git a/src/main/java/org/folio/dcb/listener/kafka/EventData.java b/src/main/java/org/folio/dcb/listener/kafka/EventData.java index 0b786a2b..579f16e0 100644 --- a/src/main/java/org/folio/dcb/listener/kafka/EventData.java +++ b/src/main/java/org/folio/dcb/listener/kafka/EventData.java @@ -8,6 +8,7 @@ public class EventData { private String itemId; private String requestId; private boolean isDcb; + private String cancellationAdditionalInformation; public enum EventType { CHECK_IN, CHECK_OUT, IN_TRANSIT, AWAITING_PICKUP, CANCEL diff --git a/src/main/java/org/folio/dcb/service/CirculationService.java b/src/main/java/org/folio/dcb/service/CirculationService.java index 319c7e20..e8641865 100644 --- a/src/main/java/org/folio/dcb/service/CirculationService.java +++ b/src/main/java/org/folio/dcb/service/CirculationService.java @@ -17,5 +17,18 @@ public interface CirculationService { */ void checkOutByBarcode(TransactionEntity dcbTransaction); - void cancelRequest(TransactionEntity dcbTransaction); + /** + * Cancels a transaction request based on the provided transaction details. + *

+ * If {@code isItemUnavailableCancellation} is {@code true}, the cancellation reason + * will be updated to indicate item unavailability, and the notification for this + * cancellation will be suppressed by setting the {@code suppressNotification} flag + * to {@code true}. + *

+ * + * @param dcbTransaction the transaction entity representing the request to be canceled + * @param isItemUnavailableCancellation a flag indicating whether the cancellation is due to item unavailability + * (true if the item is unavailable, false otherwise) + */ + void cancelRequest(TransactionEntity dcbTransaction, boolean isItemUnavailableCancellation); } diff --git a/src/main/java/org/folio/dcb/service/impl/BaseLibraryService.java b/src/main/java/org/folio/dcb/service/impl/BaseLibraryService.java index 812aaf1c..e1f6345c 100644 --- a/src/main/java/org/folio/dcb/service/impl/BaseLibraryService.java +++ b/src/main/java/org/folio/dcb/service/impl/BaseLibraryService.java @@ -110,7 +110,7 @@ public void updateTransactionStatus(TransactionEntity dcbTransaction, Transactio public void cancelTransactionRequest(TransactionEntity transactionEntity){ try { - circulationService.cancelRequest(transactionEntity); + circulationService.cancelRequest(transactionEntity, false); } catch (CirculationRequestException e) { updateTransactionEntity(transactionEntity, TransactionStatus.StatusEnum.ERROR); } @@ -145,7 +145,7 @@ public void updateTransactionDetails(TransactionEntity transactionEntity, DcbTra CirculationItem item = circulationItemService.checkIfItemExistsAndCreate(dcbItem, transactionEntity.getServicePointId()); dcbItem.setId(item.getId()); checkOpenTransactionExistsAndThrow(item.getId()); - cancelTransactionRequest(transactionEntity); + circulationService.cancelRequest(transactionEntity, true); CirculationRequest holdRequest = requestService.createHoldItemRequest(userService.fetchUser(dcbPatron), dcbItem, transactionEntity.getServicePointId()); updateItemDetailsAndSaveEntity(transactionEntity, item, dcbItem.getMaterialType(), holdRequest.getId()); diff --git a/src/main/java/org/folio/dcb/service/impl/CirculationServiceImpl.java b/src/main/java/org/folio/dcb/service/impl/CirculationServiceImpl.java index 9934385f..bf6496af 100644 --- a/src/main/java/org/folio/dcb/service/impl/CirculationServiceImpl.java +++ b/src/main/java/org/folio/dcb/service/impl/CirculationServiceImpl.java @@ -14,6 +14,8 @@ import org.springframework.stereotype.Service; import java.time.OffsetDateTime; +import static org.folio.dcb.utils.DCBConstants.ITEM_UNAVAILABLE_CANCELLATION_MSG; + @Service @Log4j2 @RequiredArgsConstructor @@ -41,11 +43,15 @@ public void checkOutByBarcode(TransactionEntity dcbTransaction) { } @Override - public void cancelRequest(TransactionEntity dcbTransaction) { + public void cancelRequest(TransactionEntity dcbTransaction, boolean isItemUnavailableCancellation) { log.debug("cancelRequest:: cancelling request using request id {} ", dcbTransaction.getRequestId()); CirculationRequest request = circulationStorageService.getCancellationRequestIfOpenOrNull(dcbTransaction.getRequestId().toString()); if (request != null){ try { + if (isItemUnavailableCancellation) { + request.setCancellationAdditionalInformation(ITEM_UNAVAILABLE_CANCELLATION_MSG); + request.setIsSuppressNotification(true); + } circulationClient.updateRequest(request.getId(), request); } catch (FeignException e) { log.warn("cancelRequest:: error cancelling request using request id {} ", dcbTransaction.getRequestId(), e); diff --git a/src/main/java/org/folio/dcb/utils/DCBConstants.java b/src/main/java/org/folio/dcb/utils/DCBConstants.java index 12bca85e..e650dcb8 100644 --- a/src/main/java/org/folio/dcb/utils/DCBConstants.java +++ b/src/main/java/org/folio/dcb/utils/DCBConstants.java @@ -26,4 +26,5 @@ private DCBConstants() {} public static final String SHADOW_TYPE = "shadow"; public static final String HOLDING_SOURCE = "folio"; public static final String DCB_CALENDAR_NAME = "DCB Calendar"; + public static final String ITEM_UNAVAILABLE_CANCELLATION_MSG = "Request cancelled due to item unavailability"; } diff --git a/src/main/java/org/folio/dcb/utils/TransactionHelper.java b/src/main/java/org/folio/dcb/utils/TransactionHelper.java index 6468ad25..5613bcc4 100644 --- a/src/main/java/org/folio/dcb/utils/TransactionHelper.java +++ b/src/main/java/org/folio/dcb/utils/TransactionHelper.java @@ -22,6 +22,7 @@ public class TransactionHelper { public static final String LASTNAME = "lastName"; public static final String DCB_INSTANCE_TITLE = "DCB_INSTANCE"; public static final String DCB_REQUESTER_LASTNAME = "DcbSystem"; + public static final String CANCELLATION_ADDITIONAL_INFORMATION = "cancellationAdditionalInformation"; private TransactionHelper(){} @@ -65,6 +66,8 @@ public static EventData parseRequestEvent(String eventPayload){ default -> log.info("parseRequestEvent:: Request status {} is not supported", requestStatus); } eventData.setDcb(checkDcbRequest(kafkaEvent)); + eventData.setCancellationAdditionalInformation(kafkaEvent.getNewNode().has(CANCELLATION_ADDITIONAL_INFORMATION) ? + kafkaEvent.getNewNode().get(CANCELLATION_ADDITIONAL_INFORMATION).asText() : null); return eventData; } return null; diff --git a/src/main/resources/swagger.api/schemas/CirculationRequest.yaml b/src/main/resources/swagger.api/schemas/CirculationRequest.yaml index a8fb0c56..71e61615 100644 --- a/src/main/resources/swagger.api/schemas/CirculationRequest.yaml +++ b/src/main/resources/swagger.api/schemas/CirculationRequest.yaml @@ -77,6 +77,9 @@ CirculationRequest: pickupServicePointId: description: The ID of the Service Point where this request can be picked up type: string + isSuppressNotification: + description: Flag to suppress sending cancellation notifications. If true, no notification will be sent when cancelling the request + type: boolean item: $ref: CirculationRequest.yaml#/item requester: diff --git a/src/test/java/org/folio/dcb/service/BaseLibraryServiceTest.java b/src/test/java/org/folio/dcb/service/BaseLibraryServiceTest.java index 8185d8d4..32241206 100644 --- a/src/test/java/org/folio/dcb/service/BaseLibraryServiceTest.java +++ b/src/test/java/org/folio/dcb/service/BaseLibraryServiceTest.java @@ -39,6 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import static org.mockito.Mockito.times; @@ -188,7 +189,7 @@ void testTransactionCancelTest(){ transactionEntity.setStatus(OPEN); TransactionStatus transactionStatus = TransactionStatus.builder().status(CANCELLED).build(); baseLibraryService.updateTransactionStatus(transactionEntity, transactionStatus); - verify(circulationService).cancelRequest(any()); + verify(circulationService).cancelRequest(any(), eq(false)); } @Test diff --git a/src/test/java/org/folio/dcb/service/CirculationServiceTest.java b/src/test/java/org/folio/dcb/service/CirculationServiceTest.java index eb461539..77f62ec3 100644 --- a/src/test/java/org/folio/dcb/service/CirculationServiceTest.java +++ b/src/test/java/org/folio/dcb/service/CirculationServiceTest.java @@ -47,7 +47,7 @@ void checkInByBarcodeWithServicePointTest(){ @Test void cancelRequestTest() { when(circulationRequestService.getCancellationRequestIfOpenOrNull(anyString())).thenReturn(createCirculationRequest()); - circulationService.cancelRequest(createTransactionEntity()); + circulationService.cancelRequest(createTransactionEntity(), false); verify(circulationClient).updateRequest(anyString(), any()); } @@ -55,7 +55,7 @@ void cancelRequestTest() { void shouldThrowExceptionWhenRequestIsNotUpdated() { when(circulationRequestService.getCancellationRequestIfOpenOrNull(anyString())).thenReturn(createCirculationRequest()); when(circulationClient.updateRequest(anyString(), any())).thenThrow(FeignException.BadRequest.class); - assertThrows(CirculationRequestException.class, () -> circulationService.cancelRequest(createTransactionEntity())); + assertThrows(CirculationRequestException.class, () -> circulationService.cancelRequest(createTransactionEntity(), false)); } }