diff --git a/src/main/java/org/folio/dcb/service/impl/TransactionAuditServiceImpl.java b/src/main/java/org/folio/dcb/service/impl/TransactionAuditServiceImpl.java index 5b6a64b1..ba2a9888 100644 --- a/src/main/java/org/folio/dcb/service/impl/TransactionAuditServiceImpl.java +++ b/src/main/java/org/folio/dcb/service/impl/TransactionAuditServiceImpl.java @@ -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; @@ -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) { @@ -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); @@ -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(); diff --git a/src/test/java/org/folio/dcb/controller/EcsRequestTransactionsApiControllerTest.java b/src/test/java/org/folio/dcb/controller/EcsRequestTransactionsApiControllerTest.java new file mode 100644 index 00000000..313f6993 --- /dev/null +++ b/src/test/java/org/folio/dcb/controller/EcsRequestTransactionsApiControllerTest.java @@ -0,0 +1,73 @@ +package org.folio.dcb.controller; + +import org.folio.dcb.domain.entity.TransactionAuditEntity; +import org.folio.dcb.repository.TransactionAuditRepository; +import org.folio.dcb.repository.TransactionRepository; +import org.folio.spring.service.SystemUserScopedExecutionService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import static org.folio.dcb.domain.dto.DcbTransaction.RoleEnum.LENDER; +import static org.folio.dcb.utils.EntityUtils.DCB_TRANSACTION_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; + +public class EcsRequestTransactionsApiControllerTest extends BaseIT { + + private static final String TRANSACTION_AUDIT_DUPLICATE_ERROR_ACTION = "DUPLICATE_ERROR"; + private static final String DUPLICATE_ERROR_TRANSACTION_ID = "-1"; + + @Autowired + private TransactionRepository transactionRepository; + @Autowired + private TransactionAuditRepository transactionAuditRepository; + @Autowired + private SystemUserScopedExecutionService systemUserScopedExecutionService; + + @Test + void createLendingEcsRequestTest() throws Exception { + removeExistedTransactionFromDbIfSoExists(); + + this.mockMvc.perform( + post("/ecs-request-transactions/" + DCB_TRANSACTION_ID) + .content(asJsonString(createEcsRequestTransactionByRole(LENDER))) + .headers(defaultHeaders()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isCreated()); + + //Trying to create another transaction with same transaction id + this.mockMvc.perform( + post("/ecs-request-transactions/" + DCB_TRANSACTION_ID) + .content(asJsonString(createEcsRequestTransactionByRole(LENDER))) + .headers(defaultHeaders()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpectAll(status().is4xxClientError(), + jsonPath("$.errors[0].code", is("DUPLICATE_ERROR"))); + + // check for DUPLICATE_ERROR propagated into transactions_audit. + systemUserScopedExecutionService.executeAsyncSystemUserScoped( + TENANT, + () -> { + TransactionAuditEntity auditExisting = transactionAuditRepository + .findLatestTransactionAuditEntityByDcbTransactionId(DCB_TRANSACTION_ID) + .orElse(null); + Assertions.assertNotNull(auditExisting); + Assertions.assertNotEquals(TRANSACTION_AUDIT_DUPLICATE_ERROR_ACTION, auditExisting.getAction()); + Assertions.assertNotEquals(DUPLICATE_ERROR_TRANSACTION_ID, auditExisting.getTransactionId()); } + ); + } + + private void removeExistedTransactionFromDbIfSoExists() { + systemUserScopedExecutionService.executeAsyncSystemUserScoped(TENANT, () -> { + if (transactionRepository.existsById(DCB_TRANSACTION_ID)){ + transactionRepository.deleteById(DCB_TRANSACTION_ID); + } + }); + } +} diff --git a/src/test/java/org/folio/dcb/utils/EntityUtils.java b/src/test/java/org/folio/dcb/utils/EntityUtils.java index e3f15754..da858634 100644 --- a/src/test/java/org/folio/dcb/utils/EntityUtils.java +++ b/src/test/java/org/folio/dcb/utils/EntityUtils.java @@ -56,6 +56,7 @@ public class EntityUtils { public static String DCB_TYPE_USER_ID = "910c512c-ebc5-40c6-96a5-a20bfd81e154"; public static String EXISTED_INVENTORY_ITEM_BARCODE = "INVENTORY_ITEM"; public static String PATRON_TYPE_USER_ID = "18c1741d-e678-4c8e-9fe7-cfaeefab5eea"; + public static String REQUEST_ID = "398501a2-5c97-4ba6-9ee7-d1cd6433cb98"; public static DcbTransaction createDcbTransactionByRole(DcbTransaction.RoleEnum role) { return DcbTransaction.builder() @@ -70,6 +71,14 @@ public static DcbTransaction createDcbTransactionByRole(DcbTransaction.RoleEnum .build(); } + public static DcbTransaction createEcsRequestTransactionByRole(DcbTransaction.RoleEnum role) { + return DcbTransaction.builder() + .requestId(REQUEST_ID) + .role(role) + .pickup(createDcbPickup()) + .build(); + } + public static org.folio.dcb.domain.dto.ServicePointRequest createServicePointRequest() { return org.folio.dcb.domain.dto.ServicePointRequest.builder() .id(PICKUP_SERVICE_POINT_ID) diff --git a/src/test/resources/mappings/requests.json b/src/test/resources/mappings/requests.json new file mode 100644 index 00000000..dfc5f9ec --- /dev/null +++ b/src/test/resources/mappings/requests.json @@ -0,0 +1,17 @@ +{ + "mappings": [ + { + "request": { + "method": "GET", + "url": "/request-storage/requests/398501a2-5c97-4ba6-9ee7-d1cd6433cb98" + }, + "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 }", + "headers": { + "Content-Type": "application/json" + } + } + } + ] +}