Skip to content

Commit

Permalink
Merge pull request #115 from folio-org/MODDCB-124
Browse files Browse the repository at this point in the history
MODDCB-124: Merge branch `ecs-tlr` into `master`
  • Loading branch information
OleksandrVidinieiev authored Nov 4, 2024
2 parents 1ef86d7 + 77722bc commit c71e4b7
Show file tree
Hide file tree
Showing 27 changed files with 452 additions and 29 deletions.
35 changes: 34 additions & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,33 @@
}
]
},
{
"id": "ecs-request-transactions",
"version": "1.0",
"handlers": [
{
"methods": [
"POST"
],
"pathPattern": "/ecs-request-transactions/{ecsRequestTransactionId}",
"permissionsRequired": [
"dcb.ecs-request.transactions.post"
],
"modulePermissions": [
"circulation-storage.requests.item.get",
"circulation-storage.requests.collection.get",
"circulation.requests.item.put",
"inventory-storage.items.item.get",
"inventory-storage.items.collection.get",
"circulation-item.item.post",
"circulation-item.collection.get",
"circulation-item.item.get",
"inventory-storage.material-types.collection.get",
"inventory-storage.loan-types.collection.get"
]
}
]
},
{
"id": "_tenant",
"version": "2.0",
Expand Down Expand Up @@ -200,7 +227,8 @@
"dcb.transactions.post",
"dcb.transactions.put",
"dcb.transactions.get",
"dcb.transactions.collection.get"
"dcb.transactions.collection.get",
"dcb.ecs-request.transactions.post"
]
},
{
Expand All @@ -222,6 +250,11 @@
"permissionName": "dcb.transactions.collection.get",
"displayName": "get updated transaction detail list",
"description": "get list of transaction updated between a given query range"
},
{
"permissionName": "dcb.ecs-request.transactions.post",
"displayName": "creates new ECS request transaction",
"description": "creates new ECS request transaction"
}
],
"metadata": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ public interface CirculationClient {
void checkOutByBarcode(@RequestBody CheckOutRequest checkOutRequest);

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

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.folio.dcb.domain.dto.DcbTransaction;
import org.folio.dcb.domain.dto.TransactionStatusResponse;
import org.folio.dcb.rest.resource.EcsRequestTransactionsApi;
import org.folio.dcb.service.EcsRequestTransactionsService;
import org.folio.dcb.service.TransactionAuditService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Log4j2
@RequiredArgsConstructor
public class EcsRequestTransactionsApiController implements EcsRequestTransactionsApi {

private final EcsRequestTransactionsService ecsRequestTransactionsService;
private final TransactionAuditService transactionAuditService;

@Override
public ResponseEntity<TransactionStatusResponse> createEcsRequestTransactions(
String ecsRequestTransactionId, DcbTransaction dcbTransaction) {

log.info("createEcsRequestTransactions:: creating ECS Request Transaction {} with ID {}",
dcbTransaction, ecsRequestTransactionId);
TransactionStatusResponse transactionStatusResponse;
try {
transactionStatusResponse = ecsRequestTransactionsService.createEcsRequestTransactions(
ecsRequestTransactionId, dcbTransaction);
} catch (Exception ex) {
transactionAuditService.logErrorIfTransactionAuditNotExists(ecsRequestTransactionId,
dcbTransaction, ex.getMessage());
throw ex;
}
return ResponseEntity.status(HttpStatus.CREATED).body(transactionStatusResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void handleLoanEvent(String data, MessageHeaders messageHeaders) {
public void handleRequestEvent(String data, MessageHeaders messageHeaders) {
String tenantId = getHeaderValue(messageHeaders, XOkapiHeaders.TENANT, null).get(0);
var eventData = parseRequestEvent(data);
if (Objects.nonNull(eventData) && eventData.isDcb() ) {
if (Objects.nonNull(eventData)) {
log.debug("dcb flow for a request event");
String requestId = eventData.getRequestId();
if (Objects.nonNull(requestId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

public interface CirculationRequestService {
CirculationRequest getCancellationRequestIfOpenOrNull(String requestId);
CirculationRequest fetchRequestById(String requestId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.folio.dcb.service;

import org.folio.dcb.domain.dto.DcbTransaction;
import org.folio.dcb.domain.dto.TransactionStatusResponse;

public interface EcsRequestTransactionsService {
TransactionStatusResponse createEcsRequestTransactions(String ecsRequestTransactionsId,
DcbTransaction dcbTransaction);
}
1 change: 1 addition & 0 deletions src/main/java/org/folio/dcb/service/RequestService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public interface RequestService {
*/
CirculationRequest createPageItemRequest(User user, DcbItem dcbItem, String pickupServicePointId);
CirculationRequest createHoldItemRequest(User user, DcbItem dcbItem, String pickupServicePointId);
void updateCirculationRequest(CirculationRequest circulationRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public List<TransactionStatus.StatusEnum> lendingChainProcessor(TransactionStatu
StatusProcessor checkInProcessor = new StatusProcessor(ITEM_CHECKED_OUT, ITEM_CHECKED_IN, false, closeProcessor);
StatusProcessor checkoutProcessor = new StatusProcessor(AWAITING_PICKUP, ITEM_CHECKED_OUT, false, checkInProcessor);
StatusProcessor awaitingPickupProcessor = new StatusProcessor(OPEN, AWAITING_PICKUP, false, checkoutProcessor);
StatusProcessor openProcessor = new StatusProcessor(CREATED, OPEN, true, awaitingPickupProcessor);
StatusProcessor openProcessor = new StatusProcessor(CREATED, OPEN, false, awaitingPickupProcessor);
startChain.setChain(openProcessor);
var statuses = process(startChain, fromStatus, toStatus);
log.info("lendingChainProcessor:: Following statuses needs to be transitioned {} ", statuses);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class CirculationRequestServiceImpl implements CirculationRequestService
private final CirculationRequestClient circulationRequestClient;
private final FolioExecutionContext folioExecutionContext;

private CirculationRequest fetchRequestById(String requestId) {
public CirculationRequest fetchRequestById(String requestId) {
log.info("fetchRequestById:: fetching request for id {} ", requestId);
try {
return circulationRequestClient.fetchRequestById(requestId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void cancelRequest(TransactionEntity dcbTransaction) {
CirculationRequest request = circulationStorageService.getCancellationRequestIfOpenOrNull(dcbTransaction.getRequestId().toString());
if (request != null){
try {
circulationClient.cancelRequest(request.getId(), request);
circulationClient.updateRequest(request.getId(), request);
} catch (FeignException e) {
log.warn("cancelRequest:: error cancelling request using request id {} ", dcbTransaction.getRequestId(), e);
throw new CirculationRequestException(String.format("Error cancelling request using request id %s", dcbTransaction.getRequestId()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.folio.dcb.service.impl;

import static org.folio.dcb.domain.dto.DcbTransaction.RoleEnum.BORROWER;
import static org.folio.dcb.domain.dto.DcbTransaction.RoleEnum.LENDER;

import java.util.UUID;

import org.folio.dcb.domain.dto.CirculationItem;
import org.folio.dcb.domain.dto.CirculationRequest;
import org.folio.dcb.domain.dto.DcbItem;
import org.folio.dcb.domain.dto.DcbPatron;
import org.folio.dcb.domain.dto.DcbPickup;
import org.folio.dcb.domain.dto.DcbTransaction;
import org.folio.dcb.domain.dto.Item;
import org.folio.dcb.domain.dto.TransactionStatusResponse;
import org.folio.dcb.exception.ResourceAlreadyExistException;
import org.folio.dcb.repository.TransactionRepository;
import org.folio.dcb.service.CirculationItemService;
import org.folio.dcb.service.CirculationRequestService;
import org.folio.dcb.service.EcsRequestTransactionsService;
import org.folio.dcb.service.RequestService;
import org.folio.dcb.utils.RequestStatus;
import org.springframework.stereotype.Service;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;

@Service
@RequiredArgsConstructor
@Log4j2
public class EcsRequestTransactionsServiceImpl implements EcsRequestTransactionsService {

private final BaseLibraryService baseLibraryService;
private final TransactionRepository transactionRepository;
private final RequestService requestService;
private final CirculationRequestService circulationRequestService;
private final CirculationItemService circulationItemService;

@Override
public TransactionStatusResponse createEcsRequestTransactions(String ecsRequestTransactionsId,
DcbTransaction dcbTransaction) {

log.info("createEcsRequestTransactions:: creating new transaction request for role {} ",
dcbTransaction.getRole());
checkEcsRequestTransactionExistsAndThrow(ecsRequestTransactionsId);
CirculationRequest circulationRequest = circulationRequestService.fetchRequestById(
dcbTransaction.getRequestId());
if (circulationRequest != null && RequestStatus.isRequestOpen(
RequestStatus.from(circulationRequest.getStatus()))) {
if (dcbTransaction.getRole() == LENDER) {
createLenderEcsRequestTransactions(ecsRequestTransactionsId, dcbTransaction, circulationRequest);
} else if(dcbTransaction.getRole() == BORROWER) {
createBorrowerEcsRequestTransactions(ecsRequestTransactionsId, dcbTransaction,
circulationRequest);
} else {
throw new IllegalArgumentException("Unimplemented role: " + dcbTransaction.getRole());
}
return TransactionStatusResponse.builder()
.status(TransactionStatusResponse.StatusEnum.CREATED)
.item(dcbTransaction.getItem())
.patron(dcbTransaction.getPatron())
.build();
} else {
throw new IllegalArgumentException("Unable to create ECS transaction as could not find open request");
}
}

private void checkEcsRequestTransactionExistsAndThrow(String dcbTransactionId) {
if (transactionRepository.existsById(dcbTransactionId)) {
throw new ResourceAlreadyExistException(
String.format("unable to create ECS transaction with ID %s as it already exists",
dcbTransactionId));
}
}

private void createLenderEcsRequestTransactions(String ecsRequestTransactionsId,
DcbTransaction dcbTransaction, CirculationRequest circulationRequest) {

dcbTransaction.setItem(DcbItem.builder()
.id(String.valueOf(circulationRequest.getItemId()))
.barcode(circulationRequest.getItem().getBarcode())
.build());
dcbTransaction.setPatron(DcbPatron.builder()
.id(String.valueOf(circulationRequest.getRequesterId()))
.barcode(circulationRequest.getRequester().getBarcode())
.build());
dcbTransaction.setPickup(DcbPickup.builder()
.servicePointId(String.valueOf(circulationRequest.getPickupServicePointId()))
.build());
baseLibraryService.saveDcbTransaction(ecsRequestTransactionsId, dcbTransaction,
dcbTransaction.getRequestId());
}

private void createBorrowerEcsRequestTransactions(String ecsRequestTransactionsId,
DcbTransaction dcbTransaction, CirculationRequest circulationRequest) {

var itemVirtual = dcbTransaction.getItem();
if (itemVirtual == null) {
throw new IllegalArgumentException("Item is required for borrower transaction");
}
baseLibraryService.checkItemExistsInInventoryAndThrow(itemVirtual.getBarcode());
CirculationItem item = circulationItemService.checkIfItemExistsAndCreate(itemVirtual, circulationRequest.getPickupServicePointId());
circulationRequest.setItemId(UUID.fromString(item.getId()));
circulationRequest.setItem(Item.builder()
.barcode(item.getBarcode())
.build());
circulationRequest.setHoldingsRecordId(UUID.fromString(item.getHoldingsRecordId()));
requestService.updateCirculationRequest(circulationRequest);
dcbTransaction.setPatron(DcbPatron.builder()
.id(String.valueOf(circulationRequest.getRequesterId()))
.barcode(circulationRequest.getRequester().getBarcode())
.build());
dcbTransaction.setPickup(DcbPickup.builder()
.servicePointId(String.valueOf(circulationRequest.getPickupServicePointId()))
.build());
baseLibraryService.saveDcbTransaction(ecsRequestTransactionsId, dcbTransaction,
dcbTransaction.getRequestId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.springframework.stereotype.Service;

import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.AWAITING_PICKUP;
import static org.folio.dcb.domain.dto.TransactionStatus.StatusEnum.CREATED;
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;
Expand Down Expand Up @@ -61,7 +62,9 @@ public void updateTransactionStatus(TransactionEntity dcbTransaction, Transactio
log.debug("updateTransactionStatus:: Updating dcbTransaction {} to status {} ", dcbTransaction, transactionStatus);
var currentStatus = dcbTransaction.getStatus();
var requestedStatus = transactionStatus.getStatus();
if (OPEN == currentStatus && AWAITING_PICKUP == requestedStatus) {
if (CREATED == currentStatus && OPEN == requestedStatus) {
updateTransactionEntity(dcbTransaction, requestedStatus);
} else if (OPEN == currentStatus && AWAITING_PICKUP == requestedStatus) {
log.info("updateTransactionStatus:: Checking in item by barcode: {} ", dcbTransaction.getItemBarcode());
circulationService.checkInByBarcode(dcbTransaction);
updateTransactionEntity(dcbTransaction, requestedStatus);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ public CirculationRequest createHoldItemRequest(User user, DcbItem item, String
return circulationClient.createRequest(circulationRequest);
}

@Override
public void updateCirculationRequest(CirculationRequest circulationRequest) {
log.debug("updateCirculationRequest:: updating circulation request with id {}",
circulationRequest.getId());
circulationClient.updateRequest(circulationRequest.getId(), circulationRequest);
}

private CirculationRequest createCirculationRequest(CirculationRequest.RequestTypeEnum type, User user, DcbItem item, String holdingsId, String instanceId, String pickupServicePointId) {
return CirculationRequest.builder()
.id(UUID.randomUUID().toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import lombok.extern.log4j.Log4j2;
import org.folio.dcb.domain.dto.DcbTransaction;
import org.folio.dcb.domain.entity.TransactionAuditEntity;
import org.folio.dcb.domain.entity.TransactionEntity;
import org.folio.dcb.domain.mapper.TransactionMapper;
import org.folio.dcb.repository.TransactionAuditRepository;
import org.folio.dcb.service.TransactionAuditService;
import org.springframework.stereotype.Service;
Expand All @@ -20,7 +18,6 @@ public class TransactionAuditServiceImpl implements TransactionAuditService {
private static final String DUPLICATE_ERROR_ACTION = "DUPLICATE_ERROR";
private static final String DUPLICATE_ERROR_TRANSACTION_ID = "-1";

private final TransactionMapper transactionMapper;
private final TransactionAuditRepository transactionAuditRepository;
@Override
public void logErrorIfTransactionAuditExists(String dcbTransactionId, String errorMsg) {
Expand All @@ -44,8 +41,7 @@ public void logErrorIfTransactionAuditExists(String dcbTransactionId, String err
@Override
public void logErrorIfTransactionAuditNotExists(String dcbTransactionId, DcbTransaction dcbTransaction, String errorMsg) {
TransactionAuditEntity auditExisting = transactionAuditRepository.findLatestTransactionAuditEntityByDcbTransactionId(dcbTransactionId).orElse(null);
TransactionEntity transactionMapped = transactionMapper.mapToEntity(dcbTransactionId, dcbTransaction);
TransactionAuditEntity auditError = generateTrnAuditEntityByTrnEntityWithError(dcbTransactionId, transactionMapped, errorMsg);
TransactionAuditEntity auditError = generateTrnAuditEntityByTrnEntityWithError(dcbTransactionId, dcbTransaction, errorMsg);

if (auditExisting != null) {
log.debug("logTheErrorForNotExistedTransactionAudit:: dcbTransactionId = {}, dcbTransaction = {}, err = {}", dcbTransactionId, dcbTransaction, errorMsg);
Expand All @@ -68,7 +64,7 @@ private TransactionAuditEntity generateTrnAuditEntityFromTheFoundOneWithError(Tr
return auditError;
}

private TransactionAuditEntity generateTrnAuditEntityByTrnEntityWithError(String dcbTransactionId, TransactionEntity trnE, String errorMsg) {
private TransactionAuditEntity generateTrnAuditEntityByTrnEntityWithError(String dcbTransactionId, DcbTransaction trnE, String errorMsg) {
String errorMessage = String.format("dcbTransactionId = %s; dcb transaction content = %s; error message = %s.", dcbTransactionId, trnE.toString(), errorMsg);

TransactionAuditEntity auditError = new TransactionAuditEntity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,10 @@ public TransactionEntity getTransactionEntityOrThrow(String dcbTransactionId) {
}

private void checkTransactionExistsAndThrow(String dcbTransactionId) {
if(transactionRepository.existsById(dcbTransactionId)) {
if (transactionRepository.existsById(dcbTransactionId)) {
throw new ResourceAlreadyExistException(
String.format("unable to create transaction with id %s as it already exists", dcbTransactionId));
}
}

}
Loading

0 comments on commit c71e4b7

Please sign in to comment.