Skip to content

Commit

Permalink
[MODDCB-105] Accept existing circulation request ID (borrowing trans…
Browse files Browse the repository at this point in the history
…action) (#82)

* MODDCB-105 Accept existing circulation request ID (borrowing transaction)

* MODDCB-105 Accept existing circulation request ID (borrowing transaction)

* MODDCB-105 Accept existing circulation request ID (borrowing transaction)

* MODDCB-105 Accept existing circulation request ID (borrowing transaction)

* MODDCB-105 Accept existing circulation request ID (borrowing transaction)
  • Loading branch information
MagzhanArtykov authored Jul 5, 2024
1 parent e9ee904 commit 1b5a8e9
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 24 deletions.
10 changes: 9 additions & 1 deletion descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,15 @@
],
"modulePermissions": [
"circulation-storage.requests.item.get",
"circulation-storage.requests.collection.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"
]
}
]
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);
}
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 @@ -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
@@ -1,20 +1,29 @@
package org.folio.dcb.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
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 static org.folio.dcb.domain.dto.DcbTransaction.RoleEnum.LENDER;

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

@Service
@RequiredArgsConstructor
Expand All @@ -23,7 +32,9 @@ public class EcsRequestTransactionsServiceImpl implements EcsRequestTransactions

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,
Expand All @@ -37,6 +48,9 @@ public TransactionStatusResponse createEcsRequestTransactions(String ecsRequestT
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());
}
Expand Down Expand Up @@ -74,4 +88,29 @@ private void createLenderEcsRequestTransactions(String ecsRequestTransactionsId,
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 @@ -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
@@ -1,5 +1,15 @@
package org.folio.dcb.controller;

import static org.folio.dcb.utils.EntityUtils.CIRCULATION_REQUEST_ID;
import static org.folio.dcb.utils.EntityUtils.createBorrowingEcsRequestTransactionByRole;
import static org.folio.dcb.utils.EntityUtils.createLendingEcsRequestTransactionByRole;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.util.UUID;

import org.folio.dcb.domain.dto.DcbTransaction;
import org.folio.dcb.domain.entity.TransactionAuditEntity;
import org.folio.dcb.repository.TransactionAuditRepository;
Expand All @@ -10,16 +20,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;

import java.util.UUID;

import static org.folio.dcb.domain.dto.DcbTransaction.RoleEnum.LENDER;
import static org.folio.dcb.utils.EntityUtils.CIRCULATION_REQUEST_ID;
import static org.folio.dcb.utils.EntityUtils.createEcsRequestTransactionByRole;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

class EcsRequestTransactionsApiControllerTest extends BaseIT {

private static final String TRANSACTION_AUDIT_DUPLICATE_ERROR_ACTION = "DUPLICATE_ERROR";
Expand All @@ -38,7 +38,7 @@ void createLendingEcsRequestTest() throws Exception {

this.mockMvc.perform(
post("/ecs-request-transactions/" + CIRCULATION_REQUEST_ID)
.content(asJsonString(createEcsRequestTransactionByRole(LENDER)))
.content(asJsonString(createLendingEcsRequestTransactionByRole()))
.headers(defaultHeaders())
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
Expand All @@ -47,7 +47,7 @@ void createLendingEcsRequestTest() throws Exception {
//Trying to create another transaction with same transaction id
this.mockMvc.perform(
post("/ecs-request-transactions/" + CIRCULATION_REQUEST_ID)
.content(asJsonString(createEcsRequestTransactionByRole(LENDER)))
.content(asJsonString(createLendingEcsRequestTransactionByRole()))
.headers(defaultHeaders())
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
Expand All @@ -67,9 +67,22 @@ void createLendingEcsRequestTest() throws Exception {
);
}

@Test
void createBorrowingEcsRequestTest() throws Exception {
removeExistedTransactionFromDbIfSoExists();

this.mockMvc.perform(
post("/ecs-request-transactions/" + CIRCULATION_REQUEST_ID)
.content(asJsonString(createBorrowingEcsRequestTransactionByRole()))
.headers(defaultHeaders())
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isCreated());
}

@Test
void checkErrorStatusForInvalidRequest() throws Exception {
DcbTransaction dcbTransaction = createEcsRequestTransactionByRole(LENDER);
DcbTransaction dcbTransaction = createLendingEcsRequestTransactionByRole();
dcbTransaction.setRequestId(UUID.randomUUID().toString());
this.mockMvc.perform(
post("/ecs-request-transactions/" + CIRCULATION_REQUEST_ID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ void checkInByBarcodeWithServicePointTest(){
void cancelRequestTest() {
when(circulationRequestService.getCancellationRequestIfOpenOrNull(anyString())).thenReturn(createCirculationRequest());
circulationService.cancelRequest(createTransactionEntity());
verify(circulationClient).cancelRequest(anyString(), any());
verify(circulationClient).updateRequest(anyString(), any());
}

@Test
void shouldThrowExceptionWhenRequestIsNotUpdated() {
when(circulationRequestService.getCancellationRequestIfOpenOrNull(anyString())).thenReturn(createCirculationRequest());
when(circulationClient.cancelRequest(anyString(), any())).thenThrow(FeignException.BadRequest.class);
when(circulationClient.updateRequest(anyString(), any())).thenThrow(FeignException.BadRequest.class);
assertThrows(CirculationRequestException.class, () -> circulationService.cancelRequest(createTransactionEntity()));
}

Expand Down
13 changes: 11 additions & 2 deletions src/test/java/org/folio/dcb/utils/EntityUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,19 @@ public static DcbTransaction createDcbTransactionByRole(DcbTransaction.RoleEnum
.build();
}

public static DcbTransaction createEcsRequestTransactionByRole(DcbTransaction.RoleEnum role) {
public static DcbTransaction createLendingEcsRequestTransactionByRole() {
return DcbTransaction.builder()
.requestId(REQUEST_ID)
.role(role)
.role(DcbTransaction.RoleEnum.LENDER)
.pickup(createDcbPickup())
.build();
}

public static DcbTransaction createBorrowingEcsRequestTransactionByRole() {
return DcbTransaction.builder()
.requestId(REQUEST_ID)
.item(createDcbItem())
.role(DcbTransaction.RoleEnum.BORROWER)
.pickup(createDcbPickup())
.build();
}
Expand Down
12 changes: 12 additions & 0 deletions src/test/resources/mappings/circulation.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@
}
}
},
{
"request": {
"method": "PUT",
"url": "/circulation/requests/398501a2-5c97-4ba6-9ee7-d1cd6433cb98"
},
"response": {
"status": 204,
"headers": {
"Content-Type": "application/json"
}
}
},
{
"request": {
"method": "POST",
Expand Down
14 changes: 13 additions & 1 deletion src/test/resources/mappings/requests.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,19 @@
},
"response": {
"status": 200,
"body": "{\n \"id\" : \"05f09b87-9022-4036-a94b-3dca1bc11f70\",\n \"requestLevel\" : \"Item\",\n \"requestType\" : \"Page\",\n \"requestDate\" : \"2024-03-07T13:54:08.655+00:00\",\n \"requesterId\" : \"2205005b-ca51-4a04-87fd-938eefa8f6de\",\n \"instanceId\" : \"5bf370e0-8cca-4d9c-82e4-5170ab2a0a39\",\n \"holdingsRecordId\" : \"e3ff6133-b9a2-4d4c-a1c9-dc1867d4df19\",\n \"itemId\" : \"100d10bf-2f06-4aa0-be15-0b95b2d9f9e3\",\n \"status\" : \"Open - Not yet filled\",\n \"position\" : 1,\n \"instance\" : {\n \"title\" : \"A semantic web primer\",\n \"identifiers\" : [ {\n \"identifierTypeId\" : \"8261054f-be78-422d-bd51-4ed9f33c3422\",\n \"value\" : \"0262012103\"\n }, {\n \"identifierTypeId\" : \"8261054f-be78-422d-bd51-4ed9f33c3422\",\n \"value\" : \"9780262012102\"\n }, {\n \"identifierTypeId\" : \"c858e4f2-2b6b-4385-842b-60732ee14abb\",\n \"value\" : \"2003065165\"\n } ],\n \"contributorNames\" : [ {\n \"name\" : \"Antoniou, Grigoris\"\n }, {\n \"name\" : \"Van Harmelen, Frank\"\n } ],\n \"publication\" : [ {\n \"publisher\" : \"MIT Press\",\n \"place\" : \"Cambridge, Mass. \",\n \"dateOfPublication\" : \"c2004\",\n \"role\" : \"Publisher\"\n } ]\n },\n \"item\" : {\n \"barcode\" : \"90000\",\n \"location\" : {\n \"name\" : \"Annex\",\n \"libraryName\" : \"Datalogisk Institut\",\n \"code\" : \"KU/CC/DI/A\"\n },\n \"enumeration\" : \"\",\n \"status\" : \"Paged\",\n \"callNumber\" : \"TK5105.88815 . A58 2004 FT MEADE\",\n \"callNumberComponents\" : {\n \"callNumber\" : \"TK5105.88815 . A58 2004 FT MEADE\"\n }\n },\n \"requester\" : {\n \"lastName\" : \"rick\",\n \"firstName\" : \"psych\",\n \"barcode\" : \"123\",\n \"patronGroup\" : {\n \"id\" : \"3684a786-6671-4268-8ed0-9db82ebca60b\",\n \"group\" : \"staff\",\n \"desc\" : \"Staff Member\"\n },\n \"patronGroupId\" : \"3684a786-6671-4268-8ed0-9db82ebca60b\"\n },\n \"fulfillmentPreference\" : \"Hold Shelf\",\n \"pickupServicePointId\" : \"3a40852d-49fd-4df2-a1f9-6e2641a6e91f\",\n \"metadata\" : {\n \"createdDate\" : \"2024-03-07T13:54:13.484+00:00\",\n \"createdByUserId\" : \"5600bae3-4ca8-42dd-bef5-4502aaea6dc7\",\n \"updatedDate\" : \"2024-03-07T13:54:14.768+00:00\",\n \"updatedByUserId\" : \"5600bae3-4ca8-42dd-bef5-4502aaea6dc7\"\n },\n \"pickupServicePoint\" : {\n \"name\" : \"Circ Desk 1\",\n \"code\" : \"cd1\",\n \"discoveryDisplayName\" : \"Circulation Desk -- Hallway\",\n \"description\" : null,\n \"shelvingLagTime\" : null,\n \"pickupLocation\" : true\n }\n }",
"body": "{\n \"id\" : \"398501a2-5c97-4ba6-9ee7-d1cd6433cb98\",\n \"requestLevel\" : \"Item\",\n \"requestType\" : \"Page\",\n \"requestDate\" : \"2024-03-07T13:54:08.655+00:00\",\n \"requesterId\" : \"2205005b-ca51-4a04-87fd-938eefa8f6de\",\n \"instanceId\" : \"5bf370e0-8cca-4d9c-82e4-5170ab2a0a39\",\n \"holdingsRecordId\" : \"e3ff6133-b9a2-4d4c-a1c9-dc1867d4df19\",\n \"itemId\" : \"100d10bf-2f06-4aa0-be15-0b95b2d9f9e3\",\n \"status\" : \"Open - Not yet filled\",\n \"position\" : 1,\n \"instance\" : {\n \"title\" : \"A semantic web primer\",\n \"identifiers\" : [ {\n \"identifierTypeId\" : \"8261054f-be78-422d-bd51-4ed9f33c3422\",\n \"value\" : \"0262012103\"\n }, {\n \"identifierTypeId\" : \"8261054f-be78-422d-bd51-4ed9f33c3422\",\n \"value\" : \"9780262012102\"\n }, {\n \"identifierTypeId\" : \"c858e4f2-2b6b-4385-842b-60732ee14abb\",\n \"value\" : \"2003065165\"\n } ],\n \"contributorNames\" : [ {\n \"name\" : \"Antoniou, Grigoris\"\n }, {\n \"name\" : \"Van Harmelen, Frank\"\n } ],\n \"publication\" : [ {\n \"publisher\" : \"MIT Press\",\n \"place\" : \"Cambridge, Mass. \",\n \"dateOfPublication\" : \"c2004\",\n \"role\" : \"Publisher\"\n } ]\n },\n \"item\" : {\n \"barcode\" : \"90000\",\n \"location\" : {\n \"name\" : \"Annex\",\n \"libraryName\" : \"Datalogisk Institut\",\n \"code\" : \"KU/CC/DI/A\"\n },\n \"enumeration\" : \"\",\n \"status\" : \"Paged\",\n \"callNumber\" : \"TK5105.88815 . A58 2004 FT MEADE\",\n \"callNumberComponents\" : {\n \"callNumber\" : \"TK5105.88815 . A58 2004 FT MEADE\"\n }\n },\n \"requester\" : {\n \"lastName\" : \"rick\",\n \"firstName\" : \"psych\",\n \"barcode\" : \"123\",\n \"patronGroup\" : {\n \"id\" : \"3684a786-6671-4268-8ed0-9db82ebca60b\",\n \"group\" : \"staff\",\n \"desc\" : \"Staff Member\"\n },\n \"patronGroupId\" : \"3684a786-6671-4268-8ed0-9db82ebca60b\"\n },\n \"fulfillmentPreference\" : \"Hold Shelf\",\n \"pickupServicePointId\" : \"3a40852d-49fd-4df2-a1f9-6e2641a6e91f\",\n \"metadata\" : {\n \"createdDate\" : \"2024-03-07T13:54:13.484+00:00\",\n \"createdByUserId\" : \"5600bae3-4ca8-42dd-bef5-4502aaea6dc7\",\n \"updatedDate\" : \"2024-03-07T13:54:14.768+00:00\",\n \"updatedByUserId\" : \"5600bae3-4ca8-42dd-bef5-4502aaea6dc7\"\n },\n \"pickupServicePoint\" : {\n \"name\" : \"Circ Desk 1\",\n \"code\" : \"cd1\",\n \"discoveryDisplayName\" : \"Circulation Desk -- Hallway\",\n \"description\" : null,\n \"shelvingLagTime\" : null,\n \"pickupLocation\" : true\n }\n }",
"headers": {
"Content-Type": "application/json"
}
}
},
{
"request": {
"method": "PUT",
"url": "/request-storage/requests/398501a2-5c97-4ba6-9ee7-d1cd6433cb98"
},
"response": {
"status": 204,
"headers": {
"Content-Type": "application/json"
}
Expand Down

0 comments on commit 1b5a8e9

Please sign in to comment.