Skip to content

Commit

Permalink
Merge pull request #46 from folio-org/MODDCB-49
Browse files Browse the repository at this point in the history
MODDCB-49
  • Loading branch information
MagzhanArtykov authored Nov 22, 2023
2 parents 04e0648 + d756aa4 commit 0665faa
Show file tree
Hide file tree
Showing 41 changed files with 537 additions and 30 deletions.
10 changes: 8 additions & 2 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,14 @@
"inventory-storage.items.item.get",
"inventory-storage.holdings.item.get",
"circulation.requests.item.post",
"circulation.requests.item.put",
"circulation-item-storage.items.item.post",
"circulation-item-storage.items.item.get",
"inventory-storage.material-types.collection.get",
"inventory-storage.loan-types.collection.get"
"inventory-storage.loan-types.collection.get",
"circulation-storage.requests.item.get",
"circulation-storage.cancellation-reasons.item.get",
"circulation-storage.cancellation-reasons.item.post"
]
},
{
Expand Down Expand Up @@ -154,7 +158,9 @@
"inventory-storage.location-units.libraries.collection.get",
"inventory-storage.loan-types.collection.get",
"inventory-storage.loan-types.collection.post",
"inventory-storage.loan-types.item.post"
"inventory-storage.loan-types.item.post",
"circulation-storage.cancellation-reasons.item.get",
"circulation-storage.cancellation-reasons.item.post"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.folio.dcb.client.feign;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.folio.spring.config.FeignClientConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(name = "cancellation-reason-storage", configuration = FeignClientConfiguration.class)
public interface CancellationReasonClient {

@GetMapping("/cancellation-reasons/{cancellationReasonId}")
CancellationReason findCancellationReason(@PathVariable("cancellationReasonId") String cancellationReasonId);

@PostMapping("/cancellation-reasons")
void createCancellationReason(@RequestBody CancellationReason cancellationReason);

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
class CancellationReason {
private String id;
private String name;
private String description;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import org.folio.dcb.domain.dto.CirculationRequest;
import org.folio.spring.config.FeignClientConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(name = "circulation", configuration = FeignClientConfiguration.class)
Expand All @@ -18,4 +20,7 @@ public interface CirculationClient {

@PostMapping("/check-out-by-barcode")
void checkOutByBarcode(@RequestBody CheckOutRequest checkOutRequest);

@PutMapping("/requests/{requestId}")
CirculationRequest cancelRequest(@PathVariable("requestId") String requestId, @RequestBody CirculationRequest circulationRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.folio.dcb.client.feign;

import org.folio.dcb.domain.dto.CirculationRequest;
import org.folio.spring.config.FeignClientConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(name = "request-storage", configuration = FeignClientConfiguration.class)
public interface CirculationRequestClient {
@GetMapping("/requests/{circulationItemId}")
CirculationRequest fetchRequestById(@PathVariable("circulationItemId") String circulationItemId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.folio.dcb.domain.dto.TransactionStatus.StatusEnum;
import org.folio.dcb.listener.entity.TransactionAuditEntityListener;

import java.util.UUID;

@Entity
@Table(name = "transactions")
@EntityListeners(TransactionAuditEntityListener.class)
Expand Down Expand Up @@ -46,6 +48,7 @@ public class TransactionEntity extends AuditableEntity {
private String patronGroup;
private String patronBarcode;
private String borrowingLibraryCode;
private UUID requestId;
@Enumerated(EnumType.STRING)
private StatusEnum status;
@Enumerated(EnumType.STRING)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.folio.dcb.exception;

public class CirculationRequestException extends RuntimeException {

public CirculationRequestException(String errorMsg) {
super(errorMsg);
}

}
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.extern.log4j.Log4j2;
import org.folio.dcb.repository.TransactionRepository;
import org.folio.dcb.service.LibraryService;
import org.folio.dcb.service.impl.BaseLibraryService;
import org.folio.spring.integration.XOkapiHeaders;
import org.folio.spring.service.SystemUserScopedExecutionService;
import org.springframework.beans.factory.annotation.Qualifier;
Expand All @@ -23,6 +24,8 @@
public class CirculationEventListener {
public static final String CHECK_IN_LISTENER_ID = "mod-dcb-check-in-listener-id";
public static final String CHECK_OUT_LOAN_LISTENER_ID = "mod-dcb-loan-listener-id";
public static final String REQUEST_LISTENER_ID = "mod-dcb-request-listener-id";

@Qualifier("lendingLibraryService")
private final LibraryService lendingLibraryService;
@Qualifier("borrowingPickupLibraryService")
Expand All @@ -31,6 +34,7 @@ public class CirculationEventListener {
private final LibraryService pickupLibraryService;
private final TransactionRepository transactionRepository;
private final SystemUserScopedExecutionService systemUserScopedExecutionService;
private final BaseLibraryService baseLibraryService;

@KafkaListener(
id = CHECK_IN_LISTENER_ID,
Expand Down Expand Up @@ -82,4 +86,24 @@ public void handleCheckOutEvent(String data, MessageHeaders messageHeaders) {
}
}
}

@KafkaListener(
id = REQUEST_LISTENER_ID,
topicPattern = "#{folioKafkaProperties.listener['request'].topicPattern}",
concurrency = "#{folioKafkaProperties.listener['request'].concurrency}")
public void handleRequestCancelEvent(String data, MessageHeaders messageHeaders) {
String tenantId = getHeaderValue(messageHeaders, XOkapiHeaders.TENANT, null).get(0);
var eventData = parseEvent(data);
if (Objects.nonNull(eventData) && eventData.getType() == EventData.EventType.CANCEL) {
String itemID = eventData.getItemId();
if (Objects.nonNull(itemID)) {
log.info("updateTransactionStatus:: Received cancel event for itemId: {}", itemID);
systemUserScopedExecutionService.executeAsyncSystemUserScoped(tenantId, () ->
transactionRepository.findTransactionByItemIdAndStatusNotInClosed(UUID.fromString(itemID))
.ifPresent(baseLibraryService::cancelTransactionEntity)
);
}
}
}

}
2 changes: 1 addition & 1 deletion src/main/java/org/folio/dcb/listener/kafka/EventData.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ public class EventData {
private String itemId;

public enum EventType {
CHECK_IN, CHECK_OUT
CHECK_IN, CHECK_OUT, CANCEL
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import static org.folio.dcb.listener.kafka.CirculationEventListener.CHECK_IN_LISTENER_ID;
import static org.folio.dcb.listener.kafka.CirculationEventListener.CHECK_OUT_LOAN_LISTENER_ID;
import static org.folio.dcb.listener.kafka.CirculationEventListener.REQUEST_LISTENER_ID;

@Component
@Log4j2
Expand All @@ -19,6 +20,7 @@ public class KafkaService {
public void restartEventListeners() {
restartEventListener(CHECK_OUT_LOAN_LISTENER_ID);
restartEventListener(CHECK_IN_LISTENER_ID);
restartEventListener(REQUEST_LISTENER_ID);
}

private void restartEventListener(String listenerId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.folio.dcb.service;

import org.folio.dcb.domain.dto.CirculationRequest;

public interface CirculationRequestService {
CirculationRequest getCancellationRequestIfOpenOrNull(String requestId);
}
3 changes: 1 addition & 2 deletions src/main/java/org/folio/dcb/service/CirculationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ public interface CirculationService {
/**
* Check in item by barcode
* @param dcbTransaction dcbTransactionEntity
* @return
*/
void checkInByBarcode(TransactionEntity dcbTransaction);

Expand All @@ -15,8 +14,8 @@ public interface CirculationService {
/**
* Check out item by barcode
* @param dcbTransaction dcbTransactionEntity
* @return
*/
void checkOutByBarcode(TransactionEntity dcbTransaction);

void cancelRequest(TransactionEntity dcbTransaction);
}
5 changes: 3 additions & 2 deletions src/main/java/org/folio/dcb/service/RequestService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.folio.dcb.service;

import org.folio.dcb.domain.dto.CirculationRequest;
import org.folio.dcb.domain.dto.DcbItem;
import org.folio.dcb.domain.dto.User;

Expand All @@ -9,6 +10,6 @@ public interface RequestService {
* @param user - userEntity
* @param dcbItem - dcbItemEntity
*/
void createPageItemRequest(User user, DcbItem dcbItem, String pickupServicePointId);
void createHoldItemRequest(User user, DcbItem dcbItem, String pickupServicePointId);
CirculationRequest createPageItemRequest(User user, DcbItem dcbItem, String pickupServicePointId);
CirculationRequest createHoldItemRequest(User user, DcbItem dcbItem, String pickupServicePointId);
}
26 changes: 23 additions & 3 deletions src/main/java/org/folio/dcb/service/impl/BaseLibraryService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.folio.dcb.domain.dto.CirculationItemRequest;
import org.folio.dcb.domain.dto.CirculationRequest;
import org.folio.dcb.domain.dto.DcbTransaction;
import org.folio.dcb.domain.dto.TransactionStatus;
import org.folio.dcb.domain.dto.TransactionStatusResponse;
import org.folio.dcb.domain.entity.TransactionEntity;
import org.folio.dcb.domain.mapper.TransactionMapper;
import org.folio.dcb.exception.CirculationRequestException;
import org.folio.dcb.repository.TransactionRepository;
import org.folio.dcb.service.CirculationItemService;
import org.folio.dcb.service.CirculationService;
Expand All @@ -20,6 +22,7 @@

import static org.folio.dcb.domain.dto.ItemStatus.NameEnum.AWAITING_PICKUP;
import static org.folio.dcb.domain.dto.ItemStatus.NameEnum.CHECKED_OUT;
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.CANCELLED;
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.CLOSED;
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.CREATED;
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.ITEM_CHECKED_IN;
Expand Down Expand Up @@ -47,8 +50,8 @@ public TransactionStatusResponse createBorrowingLibraryTransaction(String dcbTra
var user = userService.fetchUser(patron); //user is needed, but shouldn't be generated. it should be fetched.
circulationItemService.checkIfItemExistsAndCreate(itemVirtual, pickupServicePointId);

requestService.createHoldItemRequest(user, itemVirtual, pickupServicePointId);
saveDcbTransaction(dcbTransactionId, dcbTransaction);
CirculationRequest holdRequest = requestService.createHoldItemRequest(user, itemVirtual, pickupServicePointId);
saveDcbTransaction(dcbTransactionId, dcbTransaction, holdRequest.getId());

return TransactionStatusResponse.builder()
.status(TransactionStatusResponse.StatusEnum.CREATED)
Expand All @@ -57,11 +60,12 @@ public TransactionStatusResponse createBorrowingLibraryTransaction(String dcbTra
.build();
}

public void saveDcbTransaction(String dcbTransactionId, DcbTransaction dcbTransaction) {
public void saveDcbTransaction(String dcbTransactionId, DcbTransaction dcbTransaction, String requestId) {
TransactionEntity transactionEntity = transactionMapper.mapToEntity(dcbTransactionId, dcbTransaction);
if (Objects.isNull(transactionEntity)) {
throw new IllegalArgumentException("Transaction Entity is null");
}
transactionEntity.setRequestId(UUID.fromString(requestId));
transactionEntity.setStatus(CREATED);
transactionRepository.save(transactionEntity);
}
Expand Down Expand Up @@ -102,13 +106,29 @@ public void updateTransactionStatus(TransactionEntity dcbTransaction, Transactio
log.info("updateTransactionStatus:: transaction status transition from {} to {} for the item with barcode {} ",
ITEM_CHECKED_IN.getValue(), CLOSED.getValue(), dcbTransaction.getItemBarcode());
updateTransactionEntity(dcbTransaction, requestedStatus);
} else if(CANCELLED == requestedStatus) {
log.info("updateTransactionStatus:: Cancelling transaction with id: {} for Borrower/Pickup role", dcbTransaction.getId());
cancelTransactionRequest(dcbTransaction);
} else {
String errorMessage = String.format("updateTransactionStatus:: status update from %s to %s is not implemented", currentStatus, requestedStatus);
log.warn(errorMessage);
throw new IllegalArgumentException(errorMessage);
}
}

public void cancelTransactionRequest(TransactionEntity transactionEntity){
try {
circulationService.cancelRequest(transactionEntity);
} catch (CirculationRequestException e) {
updateTransactionEntity(transactionEntity, TransactionStatus.StatusEnum.ERROR);
}
}

public void cancelTransactionEntity(TransactionEntity transactionEntity) {
log.info("cancelTransactionEntity:: Transaction cancelled for itemId: {}", transactionEntity.getItemId());
updateTransactionEntity(transactionEntity, CANCELLED);
}

private void updateTransactionEntity(TransactionEntity transactionEntity, TransactionStatus.StatusEnum transactionStatusEnum) {
log.debug("updateTransactionEntity:: updating transaction entity from {} to {}", transactionEntity.getStatus(), transactionStatusEnum);
transactionEntity.setStatus(transactionStatusEnum);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.ITEM_CHECKED_IN;
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.ITEM_CHECKED_OUT;
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.OPEN;
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.CANCELLED;

@Log4j2
@Service("borrowingLibraryService")
Expand All @@ -35,7 +36,6 @@ public TransactionStatusResponse createCirculation(String dcbTransactionId, DcbT

@Override
public void updateStatusByTransactionEntity(TransactionEntity transactionEntity) {

}

@Override
Expand All @@ -60,6 +60,9 @@ public void updateTransactionStatus(TransactionEntity dcbTransaction, Transactio
log.info("updateTransactionStatus:: transaction status transition from {} to {} for the item with barcode {} ",
ITEM_CHECKED_IN.getValue(), CLOSED.getValue(), dcbTransaction.getItemBarcode());
updateTransactionEntity(dcbTransaction, requestedStatus);
} else if(CANCELLED == requestedStatus) {
log.info("updateTransactionStatus:: Cancelling transaction with id: {} for Borrower role", dcbTransaction.getId());
libraryService.cancelTransactionRequest(dcbTransaction);
} else {
String error = String.format("updateTransactionStatus:: status update from %s to %s is not implemented", currentStatus, requestedStatus);
log.warn(error);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.folio.dcb.service.impl;

import feign.FeignException;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.folio.dcb.client.feign.CirculationRequestClient;
import org.folio.dcb.domain.dto.CirculationRequest;
import org.folio.dcb.service.CirculationRequestService;
import org.folio.dcb.utils.DCBConstants;
import org.folio.dcb.utils.RequestStatus;
import org.folio.spring.FolioExecutionContext;
import org.springframework.stereotype.Service;

import java.time.OffsetDateTime;
import java.util.UUID;

@Service
@Log4j2
@RequiredArgsConstructor
public class CirculationRequestServiceImpl implements CirculationRequestService {

private final CirculationRequestClient circulationRequestClient;
private final FolioExecutionContext folioExecutionContext;

private CirculationRequest fetchRequestById(String requestId) {
log.info("fetchRequestById:: fetching request for id {} ", requestId);
try {
return circulationRequestClient.fetchRequestById(requestId);
} catch (FeignException.NotFound e) {
log.warn("Circulation request not found by id={}", requestId);
return null;
}
}

@Override
public CirculationRequest getCancellationRequestIfOpenOrNull(String requestId){
CirculationRequest request = fetchRequestById(requestId);
if(request != null && RequestStatus.isRequestOpen(RequestStatus.from(request.getStatus()))){
request.setStatus(RequestStatus.CLOSED_CANCELLED.getValue());
request.setCancelledDate(OffsetDateTime.now().toString());
request.setCancellationAdditionalInformation("Request cancelled by DCB");
request.setCancelledByUserId(folioExecutionContext.getUserId());
request.setCancellationReasonId(UUID.fromString(DCBConstants.CANCELLATION_REASON_ID));
return request;
}
return null;
}
}
Loading

0 comments on commit 0665faa

Please sign in to comment.