Skip to content

Commit

Permalink
PP-11205 Add method to search Ledger transactions
Browse files Browse the repository at this point in the history
- Added service method to search transactions for a gateway account.
- This will be used to find the last transaction for the service and archive service if no payments have been taken in the last 7 years
  • Loading branch information
kbottla committed Oct 31, 2023
1 parent f50334e commit ac96313
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package uk.gov.pay.adminusers.client.ledger.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class LedgerSearchTransactionsResponse {

@JsonProperty("total")
private int total;

@JsonProperty("count")
private int count;

@JsonProperty("results")
private List<LedgerTransaction> transactions;

public List<LedgerTransaction> getTransactions() {
return transactions;
}

public int getTotal() {
return total;
}

public int getCount() {
return count;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package uk.gov.pay.adminusers.client.ledger.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import uk.gov.service.payments.commons.api.json.ApiResponseDateTimeDeserializer;

import java.time.ZonedDateTime;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class LedgerTransaction {

private String transactionId;
private String reference;


@JsonDeserialize(using = ApiResponseDateTimeDeserializer.class)
private ZonedDateTime createdDate;

public LedgerTransaction() {
// empty constructor
Expand All @@ -38,4 +43,8 @@ public String getTransactionId() {
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}

public ZonedDateTime getCreatedDate() {
return createdDate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.gov.pay.adminusers.app.config.AdminUsersConfig;
import uk.gov.pay.adminusers.client.ledger.exception.LedgerException;
import uk.gov.pay.adminusers.client.ledger.model.LedgerSearchTransactionsResponse;
import uk.gov.pay.adminusers.client.ledger.model.LedgerTransaction;

import javax.inject.Inject;
Expand All @@ -13,7 +15,9 @@
import java.util.Optional;

import static java.lang.String.format;
import static net.logstash.logback.argument.StructuredArguments.kv;
import static org.apache.http.HttpStatus.SC_OK;
import static uk.gov.service.payments.logging.LoggingKeys.GATEWAY_ACCOUNT_ID;

public class LedgerService {

Expand All @@ -37,6 +41,25 @@ public Optional<LedgerTransaction> getTransaction(String id) {
return getTransactionFromLedger(uri);
}

public LedgerSearchTransactionsResponse searchTransactions(String gatewayAccountId, int limit) {
var uri = UriBuilder
.fromPath(ledgerUrl)
.path("/v1/transaction")
.queryParam("account_id", gatewayAccountId)
.queryParam("display_size", limit);

logger.info("Searching transactions",
kv(GATEWAY_ACCOUNT_ID, gatewayAccountId));

Response response = getResponse(uri);

if (response.getStatus() == SC_OK) {
return response.readEntity(LedgerSearchTransactionsResponse.class);
}

throw new LedgerException(response);
}

private Optional<LedgerTransaction> getTransactionFromLedger(UriBuilder uri) {
Response response = getResponse(uri);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,53 @@
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import uk.gov.pay.adminusers.app.config.AdminUsersConfig;
import uk.gov.pay.adminusers.client.ledger.exception.LedgerException;
import uk.gov.pay.adminusers.client.ledger.model.LedgerSearchTransactionsResponse;
import uk.gov.pay.adminusers.client.ledger.model.LedgerTransaction;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static java.lang.String.format;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.apache.http.HttpStatus.SC_OK;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.refEq;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class LedgerServiceTest {

@Mock
AdminUsersConfig mockConfiguration;

@Mock
private Client mockClient;

@Mock
private WebTarget mockWebTarget;

@Mock
private Invocation.Builder mockInvocationBuilder;

@Mock
private Response mockResponse;

private LedgerService serviceUnderTest;

private static final String LEDGER_URL = "http://ledgerUrl";
private static final ObjectMapper objectMapper = new ObjectMapper();

@Before
public void setUp(){
public void setUp() {
when(mockConfiguration.getLedgerBaseUrl()).thenReturn(LEDGER_URL);
when(mockClient.target(any(UriBuilder.class))).thenReturn(mockWebTarget);
when(mockWebTarget.request()).thenReturn(mockInvocationBuilder);
Expand All @@ -76,4 +78,30 @@ public void getTransaction_shouldDeserialiseLedgerPaymentTransactionCorrectly()
assertThat(transaction.getTransactionId(), is(externalId));
assertThat(transaction.getReference(), is("test event ref"));
}

@Test
public void searchTransactions_shouldDeserialiseSearchTransactionsResponseCorrectly() throws JsonProcessingException {
String externalId = "e8eq11mi2ndmauvb51qsg8hccn";
ImmutableMap<String, Object> transactionData = ImmutableMap.of(
"total", 1,
"count", 1,
"results", List.of(
Map.of("reference", "ref-1", "created_date", "2023-10-09T16:31:13.511Z",
"transaction_id", externalId, "gateway_account_id", "1")
));
String ledgerPayload = new Gson().toJson(transactionData);

when(mockResponse.readEntity(LedgerSearchTransactionsResponse.class)).thenReturn(objectMapper.readValue(ledgerPayload, LedgerSearchTransactionsResponse.class));
LedgerSearchTransactionsResponse ledgerSearchTransactionsResponse = serviceUnderTest.searchTransactions("1", 1);
assertThat(ledgerSearchTransactionsResponse.getTransactions().size(), is(1));
assertThat(ledgerSearchTransactionsResponse.getTransactions().get(0).getCreatedDate().toString(), is("2023-10-09T16:31:13.511Z"));
assertThat(ledgerSearchTransactionsResponse.getTransactions().get(0).getTransactionId(), is("e8eq11mi2ndmauvb51qsg8hccn"));
}

@Test
public void searchTransactions_shouldTHrowExceptionIfLedgerReturnsNon2xxError() throws JsonProcessingException {
when(mockResponse.getStatus()).thenReturn(SC_INTERNAL_SERVER_ERROR);

assertThrows(LedgerException.class, () -> serviceUnderTest.searchTransactions("1", 1));
}
}

0 comments on commit ac96313

Please sign in to comment.