Skip to content

Commit

Permalink
fix(add-user-receipt): Handles the case of CLOUSER_REQUESTED when pro…
Browse files Browse the repository at this point in the history
…cessing a closure update request.
  • Loading branch information
Alex Mannia committed Feb 5, 2025
1 parent 00088a0 commit d3241c2
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import it.pagopa.transactions.commands.handlers.TransactionRequestUserReceiptHandlerCommon;
import it.pagopa.transactions.exceptions.AlreadyProcessedException;
import it.pagopa.transactions.exceptions.InvalidRequestException;
import it.pagopa.transactions.exceptions.InvalidStatusException;
import it.pagopa.transactions.exceptions.ProcessingErrorException;
import it.pagopa.transactions.repositories.TransactionsEventStoreRepository;
import it.pagopa.transactions.utils.TransactionsUtils;
Expand Down Expand Up @@ -106,22 +107,33 @@ public Mono<BaseTransactionEvent<?>> handle(TransactionAddUserReceiptCommand com
)
)
.flatMap(
tx -> Mono.error(
new AlreadyProcessedException(
tx.getTransactionId(),
tx.getTransactionAuthorizationRequestData().getPspId(),
tx.getTransactionAuthorizationRequestData()
.getPaymentTypeCode(),
tx.getClientId().name(),
transactionsUtils.isWalletPayment(tx).orElseThrow(),
new UpdateTransactionStatusTracerUtils.GatewayOutcomeResult(
command.getData().addUserReceiptRequest()
.getOutcome()
.getValue(),
Optional.empty()
tx -> {
if (tx.getStatus() == TransactionStatusDto.CLOSURE_REQUESTED) {
return Mono.error(
new InvalidStatusException(
"Error processing closure update request: the transaction is in the state "
+ tx.getStatus()
)
)
)
);
}
return Mono.error(
new AlreadyProcessedException(
tx.getTransactionId(),
tx.getTransactionAuthorizationRequestData()
.getPspId(),
tx.getTransactionAuthorizationRequestData()
.getPaymentTypeCode(),
tx.getClientId().name(),
transactionsUtils.isWalletPayment(tx).orElseThrow(),
new UpdateTransactionStatusTracerUtils.GatewayOutcomeResult(
command.getData().addUserReceiptRequest()
.getOutcome()
.getValue(),
Optional.empty()
)
)
);
}
)
);
return transaction
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package it.pagopa.transactions.exceptions;

public class InvalidStatusException extends RuntimeException {
public InvalidStatusException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import it.pagopa.transactions.commands.data.AddUserReceiptData;
import it.pagopa.transactions.exceptions.AlreadyProcessedException;
import it.pagopa.transactions.exceptions.InvalidRequestException;
import it.pagopa.transactions.exceptions.InvalidStatusException;
import it.pagopa.transactions.exceptions.ProcessingErrorException;
import it.pagopa.transactions.repositories.TransactionsEventStoreRepository;
import it.pagopa.transactions.utils.TransactionsUtils;
Expand Down Expand Up @@ -750,6 +751,69 @@ void shouldReturnMonoErrorForErrorSendingEventOnTheQueue() {
assertEquals(Duration.ofSeconds(transientQueueEventsTtlSeconds), durationArgumentCaptor.getValue());
}

@Test
void shouldRejectTransactionInInvalidStateClosureRequested() {
TransactionActivatedEvent transactionActivatedEvent = transactionActivateEvent();

TransactionAuthorizationRequestedEvent authorizationRequestedEvent = transactionAuthorizationRequestedEvent();

TransactionAuthorizationCompletedEvent authorizationCompletedEvent = transactionAuthorizationCompletedEvent(
new NpgTransactionGatewayAuthorizationData(
OperationResultDto.EXECUTED,
"operationId",
"paymentEnd2EndId",
null,
null
)
);

TransactionClosureRequestedEvent transactionClosureRequestedEvent = transactionClosureRequestedEvent();

AddUserReceiptRequestDto addUserReceiptRequest = new AddUserReceiptRequestDto()
.outcome(OK)
.paymentDate(OffsetDateTime.now())
.addPaymentsItem(
new AddUserReceiptRequestPaymentsInnerDto()
.paymentToken("paymentToken")
.companyName("companyName")
.creditorReferenceId("creditorReferenceId")
.description("description")
.debtor("debtor")
.fiscalCode("fiscalCode")
.officeName("officeName")
);

TransactionActivated transaction = transactionActivated(ZonedDateTime.now().toString());

AddUserReceiptData addUserReceiptData = new AddUserReceiptData(
transaction.getTransactionId(),
addUserReceiptRequest
);

TransactionAddUserReceiptCommand requestStatusCommand = new TransactionAddUserReceiptCommand(
transaction.getPaymentNotices().stream().map(PaymentNotice::rptId).toList(),
addUserReceiptData
);

Flux<BaseTransactionEvent<Object>> events = ((Flux) Flux
.just(
transactionActivatedEvent,
authorizationRequestedEvent,
authorizationCompletedEvent,
transactionClosureRequestedEvent
));

/* preconditions */
Mockito.when(eventStoreRepository.findByTransactionIdOrderByCreationDateAsc(TRANSACTION_ID)).thenReturn(events);

/* test */
StepVerifier.create(updateStatusHandler.handle(requestStatusCommand))
.expectErrorMatches(error -> error instanceof InvalidStatusException)
.verify();

Mockito.verify(userReceiptDataEventRepository, Mockito.times(0)).save(any());
}

@Test
void shouldRejectTransactionInInvalidState() {
TransactionActivatedEvent transactionActivatedEvent = transactionActivateEvent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,33 @@ void shouldOpenCircuitBreakerForNotExcludedExceptionPerformingRetry() {

}

@Test
@Order(3)
void shouldOpenCircuitBreakerForInvalidStatusExceptionPerformingRetry() {
Retry retry = retryRegistry.retry("addUserReceipt");
long expectedFailedCallsWithoutRetryAttempt = retry.getMetrics().getNumberOfFailedCallsWithoutRetryAttempt();
long expectedFailedCallsWithRetryAttempt = retry.getMetrics().getNumberOfFailedCallsWithRetryAttempt() + 1;

/*
* Preconditions
*/
Mockito.when(transactionsViewRepository.findById(any(String.class)))
.thenReturn(Mono.error(new InvalidStatusException("Error processing request")));

StepVerifier
.create(
transactionsService.addUserReceipt("", new AddUserReceiptRequestDto())
)
.expectError(InvalidStatusException.class)
.verify();
assertEquals(
expectedFailedCallsWithoutRetryAttempt,
retry.getMetrics().getNumberOfFailedCallsWithoutRetryAttempt()
);
assertEquals(expectedFailedCallsWithRetryAttempt, retry.getMetrics().getNumberOfFailedCallsWithRetryAttempt());

}

private static CtFaultBean faultBeanWithCode(String faultCode) {
CtFaultBean fault = new CtFaultBean();
fault.setFaultCode(faultCode);
Expand Down

0 comments on commit d3241c2

Please sign in to comment.