Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prdp 359 feat add disable tx api #39

Merged
merged 13 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,9 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Tag(name = "IO Transactions REST APIs")
Expand Down Expand Up @@ -73,6 +68,22 @@ ResponseEntity<List<TransactionListItem>> getTransactionList(
@ApiResponse(responseCode = "500", description = "Service unavailable.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class)))})
@GetMapping(value = "/{transaction-id}", produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<TransactionDetailResponse> getTransactionDetails(
@RequestHeader(X_FISCAL_CODE) @NotBlank String fiscalCode,
@RequestHeader("x-fiscal-code") @NotBlank String fiscalCode,
@Parameter(description = "The id of the transaction.", required = true) @NotBlank @PathVariable("transaction-id") String transactionId);

@Operation(summary = "Disable the transaction details given its id.", security = {
@SecurityRequirement(name = "ApiKey")}, operationId = "disableTransaction")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Disabled Transactions.",
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)),
@ApiResponse(responseCode = "401", description = "Wrong or missing function key.", content = @Content(schema = @Schema())),
@ApiResponse(responseCode = "404", description = "Not found the transaction.", content = @Content(schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "422", description = "Unable to process the request.", content = @Content(schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "429", description = "Too many requests.", content = @Content(schema = @Schema())),
@ApiResponse(responseCode = "500", description = "Service unavailable.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class)))})
@PostMapping(value = "/{transaction-id}/disable", produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity disableTransaction(
@RequestHeader("x-fiscal-code") @NotBlank String fiscalCode,
@Parameter(description = "The id of the transaction.", required = true) @NotBlank @PathVariable("transaction-id") String transactionId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,10 @@ public ResponseEntity<TransactionDetailResponse> getTransactionDetails(String fi
transactionService.getTransactionDetails(fiscalCode, eventReference),
HttpStatus.OK);
}

@Override
public ResponseEntity<Void> disableTransaction(String fiscalCode, String transactionId) {
transactionService.disableTransaction(fiscalCode, transactionId);
return new ResponseEntity<>(HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ public enum AppError {
VIEW_GENERAL_NOT_FOUND_WITH_TRANSACTION_ID(HttpStatus.NOT_FOUND, VIEW_GENERAL_NOT_FOUND, "Not found a biz-events-view-general with id %s"),
VIEW_CART_NOT_FOUND_WITH_TRANSACTION_ID_AND_TAX_CODE(HttpStatus.NOT_FOUND, VIEW_CART_NOT_FOUND, "Not found a biz-events-view-cart with id %s for the given tax code"),

VIEW_USER_NOT_FOUND_WITH_TRANSACTION_ID(HttpStatus.NOT_FOUND, VIEW_USER_NOT_FOUND, "Not found a biz-events-view-user with id %s"),

VIEW_CART_NOT_FOUND_WITH_TRANSACTION_ID_FOR_USER(HttpStatus.NOT_FOUND, VIEW_CART_NOT_FOUND, "Not found a biz-events-view-cart with id %s for the given fiscal code"),

ERROR_MAPPING_BIZ_EVENT_TO_TRANSACTION_DETAIL(HttpStatus.INTERNAL_SERVER_ERROR, INVALID_DATA, "Error mapping bizEvent data to transaction details, missing property %s for bizEvent with id %s"),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Internal Server Error", "Something was wrong");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@
public interface BizEventsViewUserRepository extends CosmosRepository<BizEventsViewUser, String> {
@Query("select * from c where c.taxCode = @taxCode")
Page<BizEventsViewUser> getBizEventsViewUserByTaxCode(@Param("taxCode") String taxCode, Pageable pageable);

@Query("select * from c where c.transactionId=@transactionId c.taxCode = @fiscalCode")
BizEventsViewUser getBizEventsViewUserByTaxCodeAndTransactionId(String fiscalCode, String transactionId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
import it.gov.pagopa.bizeventsservice.model.response.transaction.TransactionDetailResponse;
import it.gov.pagopa.bizeventsservice.model.response.transaction.TransactionListResponse;


import java.util.List;

public interface ITransactionService {

/**
Expand All @@ -18,4 +15,5 @@ public interface ITransactionService {
TransactionListResponse getTransactionList(String fiscalCode, String continuationToken, Integer size);
TransactionDetailResponse getTransactionDetails(String fiscalCode, String transactionId);

void disableTransaction(String fiscalCode, String transactionId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import it.gov.pagopa.bizeventsservice.repository.BizEventsViewCartRepository;
import it.gov.pagopa.bizeventsservice.repository.BizEventsViewGeneralRepository;
import it.gov.pagopa.bizeventsservice.repository.BizEventsViewUserRepository;
import it.gov.pagopa.bizeventsservice.repository.BizEventsViewGeneralRepository;
import it.gov.pagopa.bizeventsservice.repository.BizEventsViewCartRepository;
import it.gov.pagopa.bizeventsservice.repository.BizEventsViewUserRepository;
import it.gov.pagopa.bizeventsservice.service.ITransactionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -97,6 +100,22 @@ public TransactionDetailResponse getTransactionDetails(String taxCode, String ev
return ConvertViewsToTransactionDetailResponse.convertTransactionDetails(bizEventsViewGeneral.get(), listOfCartViews);
}

@Override
public void disableTransaction(String fiscalCode, String transactionId) {
if(isInvalidFiscalCode(fiscalCode)){
throw new AppException(AppError.INVALID_FISCAL_CODE, fiscalCode);
}

BizEventsViewUser bizEventsViewUser = this.bizEventsViewUserRepository
.getBizEventsViewUserByTaxCodeAndTransactionId(fiscalCode, transactionId);
if (bizEventsViewUser == null) {
throw new AppException(AppError.VIEW_GENERAL_NOT_FOUND_WITH_TRANSACTION_ID);
}

bizEventsViewUser.setHidden(true);
bizEventsViewUserRepository.save(bizEventsViewUser);
}

private boolean isInvalidFiscalCode(String fiscalCode) {
if (fiscalCode != null && !fiscalCode.isEmpty()) {
Pattern pattern = Pattern.compile("^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

Expand All @@ -43,6 +44,8 @@ public class TransactionControllerTest {
public static final String CONTINUATION_TOKEN = "continuationToken";
public static final String SIZE_HEADER_KEY = "size";
public static final String SIZE = "10";
public static final String TRANSACTION_DISABLE_PATH = "/transactions/transaction-id/disable";

@Autowired
private MockMvc mvc;

Expand Down Expand Up @@ -126,5 +129,34 @@ void getTransactionDetailsWithInvalidFiscalCodeShouldReturnError() throws Except
.andReturn();
}

@Test
void getTransactionDisableShouldReturnOK() throws Exception {
mvc.perform(post(TRANSACTION_DISABLE_PATH)
.header(FISCAL_CODE_HEADER_KEY, VALID_FISCAL_CODE)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
verify(transactionService).disableTransaction(any(), any());
}

@Test
void getTransactionDisableWithMissingFiscalCodeShouldReturnError() throws Exception {
mvc.perform(post(TRANSACTION_DISABLE_PATH)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest())
.andReturn();
}

@Test
void getTransactionDisableithInvalidFiscalCodeShouldReturnError() throws Exception {
doAnswer(x -> {
throw new AppException(AppError.INVALID_FISCAL_CODE, INVALID_FISCAL_CODE);
}).when(transactionService).disableTransaction(anyString(), anyString());;
mvc.perform(post(TRANSACTION_DISABLE_PATH)
.header(FISCAL_CODE_HEADER_KEY, INVALID_FISCAL_CODE)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest())
.andReturn();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import java.util.*;

import static it.gov.pagopa.bizeventsservice.util.ViewGenerator.generateBizEventsViewUser;
import static org.mockito.Mockito.*;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
Expand Down Expand Up @@ -248,4 +249,35 @@ void transactionViewCartNotFoundThrowError() {

Assertions.assertEquals(HttpStatus.NOT_FOUND, appException.getHttpStatus());
}
@Test
public void transactionViewUserDisabled() {
BizEventsViewUser viewUser = generateBizEventsViewUser();
when(bizEventsViewUserRepository.getBizEventsViewUserByTaxCodeAndTransactionId(anyString(),anyString()))
.thenReturn(viewUser);
Assertions.assertDoesNotThrow(() -> transactionService.disableTransaction(
ViewGenerator.USER_TAX_CODE_WITH_TX, ViewGenerator.TRANSACTION_ID));
viewUser.setHidden(true);
verify(bizEventsViewUserRepository).save(viewUser);
}

@Test
public void transactionViewUserNotFoundThrowError() {
when(bizEventsViewUserRepository.getBizEventsViewUserByTaxCodeAndTransactionId(anyString(),anyString()))
.thenReturn(null);
AppException appException =
Assertions.assertThrows(AppException.class, () ->
transactionService.getTransactionDetails(
ViewGenerator.USER_TAX_CODE_WITH_TX, ViewGenerator.TRANSACTION_ID));
Assertions.assertEquals(HttpStatus.NOT_FOUND, appException.getHttpStatus());
}

@Test
void transactionUserViewThrowErrorForInvalidFiscalCode() {
AppException appException =
Assertions.assertThrows(AppException.class,() ->
transactionService.disableTransaction(
INVALID_FISCAL_CODE, ViewGenerator.TRANSACTION_ID));
verifyNoInteractions(bizEventsViewUserRepository);
Assertions.assertEquals(HttpStatus.BAD_REQUEST, appException.getHttpStatus());
}
}
Loading