diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml
index 12f1fb07..b7f920c1 100644
--- a/helm/values-dev.yaml
+++ b/helm/values-dev.yaml
@@ -86,6 +86,8 @@ microservice-chart:
GENERATE_PDF_RETRY_MAX_DELAY: "10000"
GENERATE_PDF_RETRY_MAX_ATTEMPTS: "1"
CONNECTION_TIMEOUT: "10000"
+ REDIS_PORT: "6380"
+ REDIS_TTL: "5" # 5 minutes
OTEL_SERVICE_NAME: "pagopabizeventsservice"
OTEL_RESOURCE_ATTRIBUTES: "service.name=pagopareceiptspdfserviceotl,deployment.environment=dev"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector.elastic-system.svc:4317"
@@ -99,6 +101,8 @@ microservice-chart:
COSMOS_DB_PRIMARY_KEY: 'cosmos-d-biz-key'
PDF_RECEIPT_SUBSCRIPTION_KEY: "bizevent-d-receiptpdfservice-subscription-key"
PDF_GENERATE_RECEIPT_SUBSCRIPTION_KEY: "bizevent-d-generatepdfservice-subscription-key"
+ REDIS_PWD: 'redis-password'
+ REDIS_HOST: 'redis-hostname'
OTEL_EXPORTER_OTLP_HEADERS: 'elastic-otl-secret-token'
keyvault:
name: "pagopa-d-bizevents-kv"
diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml
index 3ec2157a..489b0dd6 100644
--- a/helm/values-prod.yaml
+++ b/helm/values-prod.yaml
@@ -86,6 +86,8 @@ microservice-chart:
GENERATE_PDF_RETRY_MAX_DELAY: "10000"
GENERATE_PDF_RETRY_MAX_ATTEMPTS: "1"
CONNECTION_TIMEOUT: "10000"
+ REDIS_PORT: "6380"
+ REDIS_TTL: "20" # 20 minutes
OTEL_SERVICE_NAME: "pagopabizeventsservice"
OTEL_RESOURCE_ATTRIBUTES: "service.name=pagopareceiptspdfserviceotl,deployment.environment=prod"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector.elastic-system.svc:4317"
@@ -99,6 +101,8 @@ microservice-chart:
COSMOS_DB_PRIMARY_KEY: 'cosmos-p-biz-key'
PDF_RECEIPT_SUBSCRIPTION_KEY: "bizevent-p-receiptpdfservice-subscription-key"
PDF_GENERATE_RECEIPT_SUBSCRIPTION_KEY: "bizevent-p-generatepdfservice-subscription-key"
+ REDIS_PWD: 'redis-password'
+ REDIS_HOST: 'redis-hostname'
OTEL_EXPORTER_OTLP_HEADERS: 'elastic-otl-secret-token'
keyvault:
name: "pagopa-p-bizevents-kv"
diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml
index 5e630ad8..9247b702 100644
--- a/helm/values-uat.yaml
+++ b/helm/values-uat.yaml
@@ -86,6 +86,8 @@ microservice-chart:
GENERATE_PDF_RETRY_MAX_DELAY: "10000"
GENERATE_PDF_RETRY_MAX_ATTEMPTS: "1"
CONNECTION_TIMEOUT: "10000"
+ REDIS_PORT: "6380"
+ REDIS_TTL: "20" # 20 minutes
OTEL_SERVICE_NAME: "pagopabizeventsservice"
OTEL_RESOURCE_ATTRIBUTES: "service.name=pagopareceiptspdfserviceotl,deployment.environment=uat"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector.elastic-system.svc:4317"
@@ -99,6 +101,8 @@ microservice-chart:
COSMOS_DB_PRIMARY_KEY: 'cosmos-u-biz-key'
PDF_RECEIPT_SUBSCRIPTION_KEY: "bizevent-u-receiptpdfservice-subscription-key"
PDF_GENERATE_RECEIPT_SUBSCRIPTION_KEY: "bizevent-u-generatepdfservice-subscription-key"
+ REDIS_PWD: 'redis-password'
+ REDIS_HOST: 'redis-hostname'
OTEL_EXPORTER_OTLP_HEADERS: 'elastic-otl-secret-token'
keyvault:
name: "pagopa-u-bizevents-kv"
diff --git a/pom.xml b/pom.xml
index 7fdc8e19..730c709b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,6 +33,10 @@
org.springframework.boot
spring-boot-starter-validation
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/Application.java b/src/main/java/it/gov/pagopa/bizeventsservice/Application.java
index baa09e38..0f213810 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/Application.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/Application.java
@@ -13,6 +13,8 @@
public class Application {
public static void main(String[] args) {
+ // to avoid java.lang.ClassCastException for objects fetched from the REDIS cache
+ System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(Application.class, args);
}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/config/RedisConfig.java b/src/main/java/it/gov/pagopa/bizeventsservice/config/RedisConfig.java
new file mode 100644
index 00000000..a0e83fc6
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/config/RedisConfig.java
@@ -0,0 +1,54 @@
+package it.gov.pagopa.bizeventsservice.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+public class RedisConfig {
+
+ @Value("${spring.redis.host}")
+ private String redisHost;
+
+ @Value("${spring.redis.port}")
+ private int redisPort;
+
+ @Value("${spring.redis.pwd}")
+ private String redisPwd;
+
+ @Bean
+ public ObjectMapper objectMapper() {
+ final var objectMapper = new ObjectMapper().findAndRegisterModules();
+ objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+ return objectMapper;
+ }
+
+ @Bean
+ public LettuceConnectionFactory redisConnectionFactory() {
+ RedisStandaloneConfiguration redisConfiguration =
+ new RedisStandaloneConfiguration(redisHost, redisPort);
+ redisConfiguration.setPassword(redisPwd);
+ LettuceClientConfiguration lettuceConfig =
+ LettuceClientConfiguration.builder().useSsl().build();
+ return new LettuceConnectionFactory(redisConfiguration, lettuceConfig);
+ }
+
+ @Bean
+ @Qualifier("object")
+ public RedisTemplate redisObjectTemplate(
+ final LettuceConnectionFactory connectionFactory, ObjectMapper objectMapper) {
+ RedisTemplate template = new RedisTemplate<>();
+ template.setKeySerializer(new StringRedisSerializer());
+ template.setConnectionFactory(connectionFactory);
+ return template;
+ }
+}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/controller/ITransactionController.java b/src/main/java/it/gov/pagopa/bizeventsservice/controller/ITransactionController.java
index 010bd448..71b08b0f 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/controller/ITransactionController.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/controller/ITransactionController.java
@@ -34,6 +34,7 @@ public interface ITransactionController {
String X_CONTINUATION_TOKEN = "x-continuation-token";
String X_FISCAL_CODE = "x-fiscal-code";
String PAGE_SIZE = "size";
+ String PAGE_NUMBER = "page";
/**
* recovers biz-event data for the transaction list
@@ -60,6 +61,30 @@ ResponseEntity getTransactionList(
@RequestParam(name = PAGE_SIZE, required = false, defaultValue = "10") Integer size
);
+
+ /**
+ * recovers biz-event data for the transaction list
+ *
+ * @param fiscalCode tokenized user fiscal code
+ * @param page optional parameter defining page number, default to 0 (first page)
+ * @param size optional parameter defining page size, defaults to 10
+ * @return the transaction list
+ */
+ @GetMapping(value = "/cached", produces = MediaType.APPLICATION_JSON_VALUE)
+ @ApiResponses(value = {
+ @ApiResponse(responseCode = "200", description = "Obtained transaction list.",
+ content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(name = "TransactionListWrapResponse", implementation = TransactionListWrapResponse.class))),
+ @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 = "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)))})
+ @Operation(summary = "Retrieve the paged transaction list from biz events.", security = {
+ @SecurityRequirement(name = "ApiKey")}, operationId = "getTransactionList")
+ ResponseEntity getCachedTransactionList(
+ @RequestHeader(name = X_FISCAL_CODE) String fiscalCode,
+ @RequestParam(name = PAGE_NUMBER, required = false, defaultValue = "0") Integer page,
+ @RequestParam(name = PAGE_SIZE, required = false, defaultValue = "10") Integer size
+ );
@Operation(summary = "Retrieve the transaction details given its id.", security = {
@SecurityRequirement(name = "ApiKey")}, operationId = "getTransactionDetails")
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/controller/impl/TransactionController.java b/src/main/java/it/gov/pagopa/bizeventsservice/controller/impl/TransactionController.java
index cfee0cda..51fa3f54 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/controller/impl/TransactionController.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/controller/impl/TransactionController.java
@@ -50,6 +50,17 @@ public ResponseEntity getTransactionList(
.header(X_CONTINUATION_TOKEN, transactionListResponse.getContinuationToken())
.body(TransactionListWrapResponse.builder().transactions(transactionListResponse.getTransactionList()).build());
}
+
+ @Override
+ public ResponseEntity getCachedTransactionList(String fiscalCode,
+ Integer page, Integer size) {
+ TransactionListResponse transactionListResponse = transactionService.getCachedTransactionList(fiscalCode, page, size);
+ return ResponseEntity.ok()
+ .body(TransactionListWrapResponse.builder()
+ .transactions(transactionListResponse.getTransactionList())
+ .pageInfo(transactionListResponse.getPageInfo())
+ .build());
+ }
@Override
public ResponseEntity getTransactionDetails(String fiscalCode, String eventReference) {
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/entity/view/BizEventsViewUser.java b/src/main/java/it/gov/pagopa/bizeventsservice/entity/view/BizEventsViewUser.java
index 2ae83543..6a79488d 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/entity/view/BizEventsViewUser.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/entity/view/BizEventsViewUser.java
@@ -1,5 +1,7 @@
package it.gov.pagopa.bizeventsservice.entity.view;
+import java.io.Serializable;
+
import com.azure.spring.data.cosmos.core.mapping.Container;
import com.azure.spring.data.cosmos.core.mapping.GeneratedValue;
import com.azure.spring.data.cosmos.core.mapping.PartitionKey;
@@ -14,8 +16,13 @@
@Getter
@Setter
@Builder
-public class BizEventsViewUser {
- @GeneratedValue
+public class BizEventsViewUser implements Serializable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4997399615775767480L;
+
+ @GeneratedValue
private String id;
@PartitionKey
private String taxCode;
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/mapper/ConvertViewsToTransactionDetailResponse.java b/src/main/java/it/gov/pagopa/bizeventsservice/mapper/ConvertViewsToTransactionDetailResponse.java
index 87959523..5807fdec 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/mapper/ConvertViewsToTransactionDetailResponse.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/mapper/ConvertViewsToTransactionDetailResponse.java
@@ -86,9 +86,6 @@ public static TransactionListItem convertTransactionListItem(BizEventsViewUser v
totalAmount.updateAndGet(v -> v.add(amountExtracted));
}
- // check if the cart contains an item in which the user is a debtor
- boolean userHasDebtorItemInTheCart = listOfCartViews.stream().anyMatch(x -> viewUser.getTaxCode().equals(x.getDebtor().getTaxCode()));
-
return TransactionListItem.builder()
.transactionId(viewUser.getTransactionId())
.payeeName(listOfCartViews.size() > 1 ? payeeCartName : listOfCartViews.get(0).getPayee().getName())
@@ -98,7 +95,7 @@ public static TransactionListItem convertTransactionListItem(BizEventsViewUser v
.transactionDate(dateFormatZoned(viewUser.getTransactionDate()))
.isCart(listOfCartViews.size() > 1)
.isPayer(BooleanUtils.isTrue(viewUser.getIsPayer()))
- .isDebtor(userHasDebtorItemInTheCart ? userHasDebtorItemInTheCart: BooleanUtils.isTrue(viewUser.getIsDebtor()))
+ .isDebtor(BooleanUtils.isTrue(viewUser.getIsDebtor()))
.build();
}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/model/PageInfo.java b/src/main/java/it/gov/pagopa/bizeventsservice/model/PageInfo.java
new file mode 100644
index 00000000..a663274b
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/model/PageInfo.java
@@ -0,0 +1,44 @@
+package it.gov.pagopa.bizeventsservice.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+import javax.validation.constraints.Positive;
+import javax.validation.constraints.PositiveOrZero;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class PageInfo {
+
+ @JsonProperty("page")
+ @Schema(description = "Page number", required = true)
+ @PositiveOrZero
+ Integer page;
+
+ @JsonProperty("limit")
+ @Schema(description = "Required number of items per page", required = true)
+ @Positive
+ Integer limit;
+
+ @JsonProperty("items_found")
+ @Schema(description = "Number of items found. (The last page may have fewer elements than required)", required = true)
+ @PositiveOrZero
+ Integer itemsFound;
+
+ @JsonProperty("total_pages")
+ @Schema(description = "Total number of pages", required = true)
+ @PositiveOrZero
+ Integer totalPages;
+}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/model/response/transaction/TransactionListResponse.java b/src/main/java/it/gov/pagopa/bizeventsservice/model/response/transaction/TransactionListResponse.java
index 3760d8f6..65693eb6 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/model/response/transaction/TransactionListResponse.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/model/response/transaction/TransactionListResponse.java
@@ -5,9 +5,12 @@
import java.util.List;
+import it.gov.pagopa.bizeventsservice.model.PageInfo;
+
@Builder
@Getter
public class TransactionListResponse {
private List transactionList;
private String continuationToken;
+ private PageInfo pageInfo;
}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/model/response/transaction/TransactionListWrapResponse.java b/src/main/java/it/gov/pagopa/bizeventsservice/model/response/transaction/TransactionListWrapResponse.java
index 6e5f53c2..373c36ab 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/model/response/transaction/TransactionListWrapResponse.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/model/response/transaction/TransactionListWrapResponse.java
@@ -5,8 +5,17 @@
import java.util.List;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+
+import it.gov.pagopa.bizeventsservice.model.PageInfo;
+
@Builder
@Getter
+@JsonInclude(Include.NON_NULL)
public class TransactionListWrapResponse {
private List transactions;
+ @JsonProperty("page_info")
+ private PageInfo pageInfo;
}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/repository/BizEventsViewUserRepository.java b/src/main/java/it/gov/pagopa/bizeventsservice/repository/BizEventsViewUserRepository.java
index a761ba27..06fc0cf5 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/repository/BizEventsViewUserRepository.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/repository/BizEventsViewUserRepository.java
@@ -17,6 +17,9 @@
public interface BizEventsViewUserRepository extends CosmosRepository {
@Query("select * from c where c.taxCode = @taxCode and c.hidden = false")
Page getBizEventsViewUserByTaxCode(@Param("taxCode") String taxCode, Pageable pageable);
+
+ @Query("select * from c where c.taxCode = @taxCode and c.hidden = false")
+ List getBizEventsViewUserByTaxCode(@Param("taxCode") String taxCode);
@Query("select * from c where c.transactionId=@transactionId and c.taxCode = @fiscalCode and c.hidden = false")
List getBizEventsViewUserByTaxCodeAndTransactionId(String fiscalCode, String transactionId);
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/repository/redis/RedisRepository.java b/src/main/java/it/gov/pagopa/bizeventsservice/repository/redis/RedisRepository.java
new file mode 100644
index 00000000..2678b33f
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/repository/redis/RedisRepository.java
@@ -0,0 +1,29 @@
+package it.gov.pagopa.bizeventsservice.repository.redis;
+
+import java.time.Duration;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+
+@Component
+public class RedisRepository {
+
+ @Autowired
+ @Qualifier("object")
+ private RedisTemplate redisTemplateObj;
+
+ public void save(String key, byte[] value, long ttl) {
+ redisTemplateObj.opsForValue().set(key, value, Duration.ofMinutes(ttl));
+ }
+
+ public byte[] get(String key) {
+ return redisTemplateObj.opsForValue().get(key);
+ }
+
+ public void remove(String key) {
+ redisTemplateObj.delete(key);
+ }
+}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/service/ITransactionService.java b/src/main/java/it/gov/pagopa/bizeventsservice/service/ITransactionService.java
index ebabfe94..b8caf0ea 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/service/ITransactionService.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/service/ITransactionService.java
@@ -13,6 +13,7 @@ public interface ITransactionService {
* @return transaction list
*/
TransactionListResponse getTransactionList(String fiscalCode, String continuationToken, Integer size);
+ TransactionListResponse getCachedTransactionList(String fiscalCode, Integer page, Integer size);
TransactionDetailResponse getTransactionDetails(String fiscalCode, String transactionId);
void disableTransaction(String fiscalCode, String transactionId);
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/service/impl/TransactionService.java b/src/main/java/it/gov/pagopa/bizeventsservice/service/impl/TransactionService.java
index 5cf59467..97f0085b 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/service/impl/TransactionService.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/service/impl/TransactionService.java
@@ -7,19 +7,29 @@
import it.gov.pagopa.bizeventsservice.exception.AppError;
import it.gov.pagopa.bizeventsservice.exception.AppException;
import it.gov.pagopa.bizeventsservice.mapper.ConvertViewsToTransactionDetailResponse;
+import it.gov.pagopa.bizeventsservice.model.PageInfo;
import it.gov.pagopa.bizeventsservice.model.response.transaction.TransactionDetailResponse;
import it.gov.pagopa.bizeventsservice.model.response.transaction.TransactionListItem;
import it.gov.pagopa.bizeventsservice.model.response.transaction.TransactionListResponse;
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.redis.RedisRepository;
import it.gov.pagopa.bizeventsservice.service.ITransactionService;
+import it.gov.pagopa.bizeventsservice.util.Constants;
+import it.gov.pagopa.bizeventsservice.util.Util;
+
+import org.apache.commons.lang3.SerializationUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -30,12 +40,18 @@ public class TransactionService implements ITransactionService {
private final BizEventsViewGeneralRepository bizEventsViewGeneralRepository;
private final BizEventsViewCartRepository bizEventsViewCartRepository;
private final BizEventsViewUserRepository bizEventsViewUserRepository;
+ private final RedisRepository redisRepository;
+
+ @Value("${spring.redis.ttl}")
+ private long redisTTL;
@Autowired
- public TransactionService(BizEventsViewGeneralRepository bizEventsViewGeneralRepository, BizEventsViewCartRepository bizEventsViewCartRepository, BizEventsViewUserRepository bizEventsViewUserRepository) {
+ public TransactionService(BizEventsViewGeneralRepository bizEventsViewGeneralRepository, BizEventsViewCartRepository bizEventsViewCartRepository,
+ BizEventsViewUserRepository bizEventsViewUserRepository, RedisRepository redisRepository) {
this.bizEventsViewGeneralRepository = bizEventsViewGeneralRepository;
this.bizEventsViewCartRepository = bizEventsViewCartRepository;
this.bizEventsViewUserRepository = bizEventsViewUserRepository;
+ this.redisRepository = redisRepository;
}
@Override
@@ -47,7 +63,9 @@ public TransactionListResponse getTransactionList(
final CosmosPageRequest pageRequest = new CosmosPageRequest(0, size, continuationToken, sort);
final Page page = this.bizEventsViewUserRepository.getBizEventsViewUserByTaxCode(taxCode, pageRequest);
Set set = new HashSet<>(page.getContent().size());
- List listOfViewUser = page.getContent().stream().filter(p -> set.add(p.getTransactionId())).toList();
+ List listOfViewUser = page.getContent().stream()
+ .sorted(Comparator.comparing(BizEventsViewUser::getIsDebtor,Comparator.reverseOrder()))
+ .filter(p -> set.add(p.getTransactionId())).toList();
if(listOfViewUser.isEmpty()){
throw new AppException(AppError.VIEW_USER_NOT_FOUND_WITH_TAX_CODE, taxCode);
@@ -74,6 +92,38 @@ public TransactionListResponse getTransactionList(
.continuationToken(nextToken)
.build();
}
+
+ @Override
+ public TransactionListResponse getCachedTransactionList(String taxCode, Integer page, Integer size) {
+
+ List listOfTransactionListItem = new ArrayList<>();
+
+ List> pagedListOfViewUser = this.retrievePaginatedList(taxCode, size);
+
+ for (BizEventsViewUser viewUser : pagedListOfViewUser.get(page)) {
+ List listOfViewCart;
+ if(Boolean.TRUE.equals(viewUser.getIsPayer())){
+ listOfViewCart = this.bizEventsViewCartRepository.getBizEventsViewCartByTransactionId(viewUser.getTransactionId());
+ } else {
+ listOfViewCart = this.bizEventsViewCartRepository.getBizEventsViewCartByTransactionIdAndFilteredByTaxCode(viewUser.getTransactionId(), taxCode);
+ }
+
+ if (!listOfViewCart.isEmpty()) {
+ TransactionListItem transactionListItem = ConvertViewsToTransactionDetailResponse.convertTransactionListItem(viewUser, listOfViewCart);
+ listOfTransactionListItem.add(transactionListItem);
+ }
+ }
+
+ return TransactionListResponse.builder()
+ .transactionList(listOfTransactionListItem)
+ .pageInfo(PageInfo.builder()
+ .limit(size)
+ .page(page)
+ .itemsFound(pagedListOfViewUser.stream().mapToInt(i -> i.size()).sum())
+ .totalPages(pagedListOfViewUser.size())
+ .build())
+ .build();
+ }
@Override
public TransactionDetailResponse getTransactionDetails(String taxCode, String eventReference) {
@@ -106,4 +156,25 @@ public void disableTransaction(String fiscalCode, String transactionId) {
bizEventsViewUser.setHidden(true);
bizEventsViewUserRepository.save(bizEventsViewUser);
}
+
+ private List> retrievePaginatedList (String taxCode, Integer size) {
+ List> pagedListOfViewUser = null;
+ byte [] data;
+ // read from the REDIS cache for the paginated list
+ if ((data=redisRepository.get(Constants.REDIS_KEY_PREFIX+taxCode)) != null){
+ pagedListOfViewUser = SerializationUtils.deserialize(data);
+ } else {
+ List fullListOfViewUser = this.bizEventsViewUserRepository.getBizEventsViewUserByTaxCode(taxCode);
+ if(CollectionUtils.isEmpty(fullListOfViewUser)){
+ throw new AppException(AppError.VIEW_USER_NOT_FOUND_WITH_TAX_CODE, taxCode);
+ }
+ pagedListOfViewUser = Util.getPaginatedList(fullListOfViewUser, size);
+ // write in the REDIS cache the paginated list
+ redisRepository.save(Constants.REDIS_KEY_PREFIX+taxCode, SerializationUtils.serialize((Serializable)pagedListOfViewUser), redisTTL);
+ }
+ return pagedListOfViewUser;
+ }
+
+
+
}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/util/Constants.java b/src/main/java/it/gov/pagopa/bizeventsservice/util/Constants.java
index 516c155e..6811f415 100644
--- a/src/main/java/it/gov/pagopa/bizeventsservice/util/Constants.java
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/util/Constants.java
@@ -13,6 +13,7 @@ public class Constants {
public static final String VIEW_GENERAL_NOT_FOUND = "Biz-events-view-general not found";
public static final String VIEW_CART_NOT_FOUND = "Biz-events-view-cart not found";
public static final String INVALID_DATA = "Invalid Data";
+ public static final String REDIS_KEY_PREFIX = "trx_";
}
diff --git a/src/main/java/it/gov/pagopa/bizeventsservice/util/Util.java b/src/main/java/it/gov/pagopa/bizeventsservice/util/Util.java
new file mode 100644
index 00000000..e022feb6
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/bizeventsservice/util/Util.java
@@ -0,0 +1,51 @@
+package it.gov.pagopa.bizeventsservice.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import it.gov.pagopa.bizeventsservice.entity.view.BizEventsViewUser;
+
+public class Util {
+
+ private Util() {}
+
+ public static List> getPaginatedList(List fullListOfViewUser, int pageSize) {
+ Set set = new HashSet<>(fullListOfViewUser.size());
+ // sorting based on the isDebtor field (true first) and then grouping by transactionId (the cart case requires that only one item be taken from those present)
+ List mergedListByTIDOfViewUser = fullListOfViewUser.stream()
+ .sorted(Comparator.comparing(BizEventsViewUser::getIsDebtor,Comparator.reverseOrder()))
+ .filter(p -> set.add(p.getTransactionId())).collect(Collectors.toList());
+
+ // sorting by transactionDate as per business request
+ Collections.sort(mergedListByTIDOfViewUser,
+ Comparator.comparing(BizEventsViewUser::getTransactionDate,
+ Comparator.nullsLast(Comparator.naturalOrder()))
+ .reversed());
+
+ return Util.getPages(mergedListByTIDOfViewUser, pageSize);
+ }
+
+ public static List> getPages(Collection c, Integer pageSize) {
+
+ List list = new ArrayList<>(c);
+
+ if (pageSize == null || pageSize <= 0 || pageSize > list.size()) {
+ pageSize = list.size();
+ }
+
+ int numPages = (int) Math.ceil((double)list.size() / (double)pageSize);
+ List> pages = new ArrayList<>(numPages);
+ for (int pageNum = 0; pageNum < numPages; pageNum++) {
+ int toIndex = pageNum;
+ // subList() method is an instance of 'RandomAccessSubList' which is not serializable --> create a new ArrayList which is
+ pages.add(new ArrayList<>(list.subList(pageNum * pageSize, Math.min(++toIndex * pageSize, list.size()))));
+ }
+ return pages;
+ }
+}
diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties
index 69cb62c9..9592b67d 100644
--- a/src/main/resources/application-dev.properties
+++ b/src/main/resources/application-dev.properties
@@ -24,6 +24,13 @@ service.get.pdf.receipt.host=https://api.dev.platform.pagopa.it/receipts/service
service.generate.pdf.receipt.host=https://api.dev.platform.pagopa.it/receipts/helpdesk/v1
service.generate.pdf.receipt.path=/receipts/{event-id}/regenerate-receipt-pdf
+# Redis configuration
+spring.redis.host=pagopa-d-redis.redis.cache.windows.net
+spring.redis.port=6380
+spring.redis.pwd=${REDIS_PWD}
+# 5 min
+spring.redis.ttl=5
+
springdoc.group-configs[0].group=all
springdoc.group-configs[0].displayName=Biz-Events All
springdoc.group-configs[0].paths-to-match=/**
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index edcc11b0..0f6ec71e 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -55,6 +55,13 @@ get.pdf.retry.maxDelay=${GET_PDF_RETRY_MAX_DELAY:10000}
generate.pdf.retry.maxAttempts=${GENERATE_PDF_RETRY_MAX_ATTEMPTS:3}
generate.pdf.retry.maxDelay=${GENERATE_PDF_RETRY_MAX_DELAY:10000}
+# Redis
+spring.redis.host=${REDIS_HOST}
+spring.redis.port=${REDIS_PORT}
+spring.redis.pwd=${REDIS_PWD}
+# default 20 min
+spring.redis.ttl=${REDIS_TTL:20}
+
# Openapi
springdoc.use-fqn=false
diff --git a/src/test/java/it/gov/pagopa/bizeventsservice/controller/TransactionControllerTest.java b/src/test/java/it/gov/pagopa/bizeventsservice/controller/TransactionControllerTest.java
index 542798f6..669707f3 100644
--- a/src/test/java/it/gov/pagopa/bizeventsservice/controller/TransactionControllerTest.java
+++ b/src/test/java/it/gov/pagopa/bizeventsservice/controller/TransactionControllerTest.java
@@ -48,12 +48,15 @@ public class TransactionControllerTest {
public static final String INVALID_FISCAL_CODE = "INVALID_TX_FISCAL_CODE";
public static final String VALID_FISCAL_CODE = "AAAAAA00A00A000A";
public static final String LIST_TRANSACTION_PATH = "/transactions";
+ public static final String LIST_CACHED_TRANSACTION_PATH = "/transactions/cached";
public static final String FISCAL_CODE_HEADER_KEY = "x-fiscal-code";
public static final String TRANSACTION_DETAILS_PATH = "/transactions/transaction-id";
private static final String CONTINUATION_TOKEN_HEADER_KEY = "x-continuation-token";
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 PAGE_HEADER_KEY = "page";
+ public static final String PAGE_NUM = "0";
public static final String TRANSACTION_DISABLE_PATH = "/transactions/transaction-id/disable";
public static final String TRANSACTION_RECEIPT_PATH = "/transactions/event-id/pdf";
@@ -81,6 +84,7 @@ void setUp() throws IOException {
TransactionListResponse transactionListResponse = TransactionListResponse.builder().transactionList(transactionListItems).build();
TransactionDetailResponse transactionDetailResponse = TestUtil.readModelFromFile("biz-events/transactionDetails.json", TransactionDetailResponse.class);
when(transactionService.getTransactionList(eq(VALID_FISCAL_CODE), anyString(), anyInt())).thenReturn(transactionListResponse);
+ when(transactionService.getCachedTransactionList(eq(VALID_FISCAL_CODE), anyInt(), anyInt())).thenReturn(transactionListResponse);
when(transactionService.getTransactionDetails(anyString(), anyString())).thenReturn(transactionDetailResponse);
Attachment attachmentDetail = mock (Attachment.class);
AttachmentsDetailsResponse attachments = AttachmentsDetailsResponse.builder().attachments(Arrays.asList(attachmentDetail)).build();
@@ -123,6 +127,21 @@ void getListTransactionWithInvalidFiscalCodeShouldReturnError() throws Exception
.andExpect(status().isBadRequest())
.andReturn();
}
+
+ @Test
+ void getCachedListTransactionShouldReturnData() throws Exception {
+ MvcResult result = mvc.perform(get(LIST_CACHED_TRANSACTION_PATH)
+ .header(FISCAL_CODE_HEADER_KEY, VALID_FISCAL_CODE)
+ .queryParam(SIZE_HEADER_KEY, SIZE)
+ .queryParam(PAGE_HEADER_KEY, PAGE_NUM)
+ .contentType(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andReturn();
+ assertNotNull(result.getResponse().getContentAsString());
+ assertTrue(result.getResponse().getContentAsString().contains("b77d4987-a3e4-48d4-a2fd-af504f8b79e9"));
+ assertTrue(result.getResponse().getContentAsString().contains("100.0"));
+ }
@Test
void getTransactionDetailsShouldReturnData() throws Exception {
diff --git a/src/test/java/it/gov/pagopa/bizeventsservice/service/TransactionServiceTest.java b/src/test/java/it/gov/pagopa/bizeventsservice/service/TransactionServiceTest.java
index 455e4960..de60e407 100644
--- a/src/test/java/it/gov/pagopa/bizeventsservice/service/TransactionServiceTest.java
+++ b/src/test/java/it/gov/pagopa/bizeventsservice/service/TransactionServiceTest.java
@@ -9,8 +9,12 @@
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.redis.RedisRepository;
import it.gov.pagopa.bizeventsservice.service.impl.TransactionService;
+import it.gov.pagopa.bizeventsservice.util.Util;
import it.gov.pagopa.bizeventsservice.util.ViewGenerator;
+
+import org.apache.commons.lang3.SerializationUtils;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
@@ -20,6 +24,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.test.context.ContextConfiguration;
+import java.io.Serializable;
import java.util.*;
import static it.gov.pagopa.bizeventsservice.util.ViewGenerator.generateBizEventsViewUser;
@@ -32,7 +37,9 @@
public class TransactionServiceTest {
public static final String INVALID_FISCAL_CODE = "invalidFiscalCode";
public static final int PAGE_SIZE = 5;
+ public static final int PAGE_NUMBER = 0;
public static final String CONTINUATION_TOKEN = "0";
+ public static final String TRANSACTION_ID = "transactionId";
@MockBean
private BizEventsViewUserRepository bizEventsViewUserRepository;
@@ -40,6 +47,8 @@ public class TransactionServiceTest {
private BizEventsViewGeneralRepository bizEventsViewGeneralRepository;
@MockBean
private BizEventsViewCartRepository bizEventsViewCartRepository;
+ @MockBean
+ private RedisRepository redisRepository;
private TransactionService transactionService;
@Value("${transaction.payee.cartName:Pagamento Multiplo}")
@@ -47,7 +56,7 @@ public class TransactionServiceTest {
@BeforeEach
void setUp() {
- transactionService = spy(new TransactionService(bizEventsViewGeneralRepository, bizEventsViewCartRepository, bizEventsViewUserRepository));
+ transactionService = spy(new TransactionService(bizEventsViewGeneralRepository, bizEventsViewCartRepository, bizEventsViewUserRepository, redisRepository));
}
@Test
@@ -237,7 +246,7 @@ void transactionViewCartNotFoundThrowError() {
Assertions.assertEquals(HttpStatus.NOT_FOUND, appException.getHttpStatus());
}
@Test
- public void transactionViewUserDisabled() {
+ void transactionViewUserDisabled() {
List viewUserList = Collections.singletonList(generateBizEventsViewUser());
when(bizEventsViewUserRepository.getBizEventsViewUserByTaxCodeAndTransactionId(anyString(),anyString()))
.thenReturn(viewUserList);
@@ -248,7 +257,7 @@ public void transactionViewUserDisabled() {
}
@Test
- public void transactionViewUserNotFoundThrowError() {
+ void transactionViewUserNotFoundThrowError() {
when(bizEventsViewUserRepository.getBizEventsViewUserByTaxCodeAndTransactionId(anyString(),anyString()))
.thenReturn(null);
AppException appException =
@@ -257,4 +266,96 @@ public void transactionViewUserNotFoundThrowError() {
ViewGenerator.USER_TAX_CODE_WITH_TX, ViewGenerator.TRANSACTION_ID));
Assertions.assertEquals(HttpStatus.NOT_FOUND, appException.getHttpStatus());
}
+
+ @Test
+ void notCachedTaxCodeWithEventsShouldReturnTransactionList() {
+ List listOfViewUser = ViewGenerator.generateListOf95MixedBizEventsViewUser();
+ when(bizEventsViewUserRepository.getBizEventsViewUserByTaxCode(ViewGenerator.USER_TAX_CODE_WITH_TX)).thenReturn(listOfViewUser);
+ List listOfSingleViewCart = Collections.singletonList(ViewGenerator.generateBizEventsViewCart());
+ List listOfMultiViewCart = ViewGenerator.generateListOfFiveViewCart();
+ when(bizEventsViewCartRepository.getBizEventsViewCartByTransactionIdAndFilteredByTaxCode(contains("_cart_"), eq(ViewGenerator.USER_TAX_CODE_WITH_TX)))
+ .thenReturn(listOfMultiViewCart);
+ when(bizEventsViewCartRepository.getBizEventsViewCartByTransactionIdAndFilteredByTaxCode(contains("_nocart"), eq(ViewGenerator.USER_TAX_CODE_WITH_TX)))
+ .thenReturn(listOfSingleViewCart);
+ // taxcode is not in cache
+ when(redisRepository.get(anyString())).thenReturn(null);
+
+
+ // invoke service to get first page
+ TransactionListResponse transactionListResponse =
+ Assertions.assertDoesNotThrow(() ->
+ transactionService.getCachedTransactionList(
+ ViewGenerator.USER_TAX_CODE_WITH_TX, PAGE_NUMBER, PAGE_SIZE));
+ Assertions.assertEquals(PAGE_NUMBER, transactionListResponse.getPageInfo().getPage());
+ Assertions.assertEquals(18, transactionListResponse.getPageInfo().getTotalPages());
+ Assertions.assertEquals(PAGE_SIZE, transactionListResponse.getPageInfo().getLimit());
+ Assertions.assertEquals(88, transactionListResponse.getPageInfo().getItemsFound());
+ List transactionListItems = transactionListResponse.getTransactionList();
+ Assertions.assertNotNull(transactionListItems);
+ Assertions.assertEquals(5, transactionListItems.size());
+ Assertions.assertEquals("2024-06-12T11:07:46Z", transactionListItems.get(0).getTransactionDate());
+
+ // invoke service to get last page
+ transactionListResponse =
+ Assertions.assertDoesNotThrow(() ->
+ transactionService.getCachedTransactionList(
+ ViewGenerator.USER_TAX_CODE_WITH_TX, 17, PAGE_SIZE));
+ Assertions.assertEquals(17, transactionListResponse.getPageInfo().getPage());
+ Assertions.assertEquals(18, transactionListResponse.getPageInfo().getTotalPages());
+ Assertions.assertEquals(PAGE_SIZE, transactionListResponse.getPageInfo().getLimit());
+ Assertions.assertEquals(88, transactionListResponse.getPageInfo().getItemsFound());
+ transactionListItems = transactionListResponse.getTransactionList();
+ Assertions.assertNotNull(transactionListItems);
+ Assertions.assertEquals(3, transactionListItems.size());
+ Assertions.assertEquals("2024-06-07T11:07:46Z", transactionListItems.get(2).getTransactionDate());
+
+ verify(bizEventsViewUserRepository, times(2)).getBizEventsViewUserByTaxCode(ViewGenerator.USER_TAX_CODE_WITH_TX);
+ verifyNoMoreInteractions(bizEventsViewUserRepository);
+ }
+
+ @Test
+ void cachedTaxCodeWithEventsShouldReturnTransactionList() {
+ List listOfViewUser = ViewGenerator.generateListOf95MixedBizEventsViewUser();
+ when(bizEventsViewUserRepository.getBizEventsViewUserByTaxCode(ViewGenerator.USER_TAX_CODE_WITH_TX)).thenReturn(listOfViewUser);
+ List listOfSingleViewCart = Collections.singletonList(ViewGenerator.generateBizEventsViewCart());
+ List listOfMultiViewCart = ViewGenerator.generateListOfFiveViewCart();
+ when(bizEventsViewCartRepository.getBizEventsViewCartByTransactionIdAndFilteredByTaxCode(contains("_cart_"), eq(ViewGenerator.USER_TAX_CODE_WITH_TX)))
+ .thenReturn(listOfMultiViewCart);
+ when(bizEventsViewCartRepository.getBizEventsViewCartByTransactionIdAndFilteredByTaxCode(contains("_nocart"), eq(ViewGenerator.USER_TAX_CODE_WITH_TX)))
+ .thenReturn(listOfSingleViewCart);
+ // taxcode is in cache
+ byte[] data = SerializationUtils.serialize((Serializable)Util.getPaginatedList(listOfViewUser, PAGE_SIZE));
+ when(redisRepository.get(anyString())).thenReturn(data);
+
+
+ // invoke service to get first page
+ TransactionListResponse transactionListResponse =
+ Assertions.assertDoesNotThrow(() ->
+ transactionService.getCachedTransactionList(
+ ViewGenerator.USER_TAX_CODE_WITH_TX, PAGE_NUMBER, PAGE_SIZE));
+ Assertions.assertEquals(PAGE_NUMBER, transactionListResponse.getPageInfo().getPage());
+ Assertions.assertEquals(18, transactionListResponse.getPageInfo().getTotalPages());
+ Assertions.assertEquals(PAGE_SIZE, transactionListResponse.getPageInfo().getLimit());
+ Assertions.assertEquals(88, transactionListResponse.getPageInfo().getItemsFound());
+ List transactionListItems = transactionListResponse.getTransactionList();
+ Assertions.assertNotNull(transactionListItems);
+ Assertions.assertEquals(5, transactionListItems.size());
+ Assertions.assertEquals("2024-06-12T11:07:46Z", transactionListItems.get(0).getTransactionDate());
+
+ // invoke service to get last page
+ transactionListResponse =
+ Assertions.assertDoesNotThrow(() ->
+ transactionService.getCachedTransactionList(
+ ViewGenerator.USER_TAX_CODE_WITH_TX, 17, PAGE_SIZE));
+ Assertions.assertEquals(17, transactionListResponse.getPageInfo().getPage());
+ Assertions.assertEquals(18, transactionListResponse.getPageInfo().getTotalPages());
+ Assertions.assertEquals(PAGE_SIZE, transactionListResponse.getPageInfo().getLimit());
+ Assertions.assertEquals(88, transactionListResponse.getPageInfo().getItemsFound());
+ transactionListItems = transactionListResponse.getTransactionList();
+ Assertions.assertNotNull(transactionListItems);
+ Assertions.assertEquals(3, transactionListItems.size());
+ Assertions.assertEquals("2024-06-07T11:07:46Z", transactionListItems.get(2).getTransactionDate());
+
+ verify(bizEventsViewUserRepository, times(0)).getBizEventsViewUserByTaxCode(ViewGenerator.USER_TAX_CODE_WITH_TX);
+ }
}
diff --git a/src/test/java/it/gov/pagopa/bizeventsservice/util/ViewGenerator.java b/src/test/java/it/gov/pagopa/bizeventsservice/util/ViewGenerator.java
index d93bfc7b..97081365 100644
--- a/src/test/java/it/gov/pagopa/bizeventsservice/util/ViewGenerator.java
+++ b/src/test/java/it/gov/pagopa/bizeventsservice/util/ViewGenerator.java
@@ -51,6 +51,35 @@ public static List generateListOfFiveBizEventsViewUser(){
}
return listOfViewUser;
}
+
+ public static List generateListOf95MixedBizEventsViewUser(){
+ List listOfViewUser = new ArrayList<>();
+ for(int i = 0; i < 85; i++){
+ BizEventsViewUser viewUser = generateBizEventsViewUser();
+ viewUser.setTransactionId(viewUser.getTransactionId()+"_nocart_"+i);
+ viewUser.setTransactionDate("2024-06-08T12:07:46Z");
+ listOfViewUser.add(viewUser);
+ }
+ for(int i = 0; i < 5; i++){
+ BizEventsViewUser viewUser = generateBizEventsViewUser();
+ viewUser.setTransactionId(viewUser.getTransactionId()+"_cart_1");
+ viewUser.setTransactionDate("2024-06-12T11:07:46Z");
+ listOfViewUser.add(viewUser);
+ }
+ for(int i = 0; i < 3; i++){
+ BizEventsViewUser viewUser = generateBizEventsViewUser();
+ viewUser.setTransactionId(viewUser.getTransactionId()+"_cart_2");
+ viewUser.setTransactionDate("2024-06-10T11:07:46Z");
+ listOfViewUser.add(viewUser);
+ }
+ for(int i = 0; i < 2; i++){
+ BizEventsViewUser viewUser = generateBizEventsViewUser();
+ viewUser.setTransactionId(viewUser.getTransactionId()+"_cart_3");
+ viewUser.setTransactionDate("2024-06-07T11:07:46Z");
+ listOfViewUser.add(viewUser);
+ }
+ return listOfViewUser;
+ }
public static BizEventsViewGeneral generateBizEventsViewGeneral(){
return BizEventsViewGeneral.builder()
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index 68061748..e1570346 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -44,6 +44,13 @@ service.get.pdf.receipt.host=http://localhost:8080/receipts/service/v1
service.generate.pdf.receipt.host=http://localhost:8080/receipts/helpdesk/v1
service.generate.pdf.receipt.path=/receipts/{event-id}/regenerate-receipt-pdf
+# Redis configuration
+spring.redis.host=pagopa-d-redis.redis.cache.windows.net
+spring.redis.port=6380
+spring.redis.pwd=pwd
+# 5 min
+spring.redis.ttl=5
+
# Openapi
springdoc.use-fqn=false
springdoc.writer-with-order-by-keys=false