diff --git a/src/main/java/it/gov/pagopa/fdr/controller/interfaces/controller/IOrganizationsController.java b/src/main/java/it/gov/pagopa/fdr/controller/interfaces/controller/IOrganizationsController.java
index 1d7f3325..b0db34d3 100644
--- a/src/main/java/it/gov/pagopa/fdr/controller/interfaces/controller/IOrganizationsController.java
+++ b/src/main/java/it/gov/pagopa/fdr/controller/interfaces/controller/IOrganizationsController.java
@@ -44,13 +44,14 @@ public interface IOrganizationsController {
summary = "Get all published flow by creditor institution",
description =
"""
-This API permits to search all published flows for a specific creditor institution,
-formatted in a paginated view. The search can be enhanced including the PSP identifier
-in order to filter only the flows for certain PSP.
-Before executing the query, the search filters are validated against entities configured for
-Nodo dei Pagamenti environment, in particular on PSP (if that search filter is defined).
-The result of the query is paginated and contains all the metadata needed for pagination purposes.
-""")
+ This API permits to search all published flows for a specific creditor institution,
+ formatted in a paginated view. The search can be enhanced including the PSP identifier
+ in order to filter only the flows for certain PSP. The only flows retrieved are the latest
+ revision, as same as "nodoChiediElencoFlussiRendicontazione" primitive does.
+ Before executing the query, the search filters are validated against entities configured for
+ Nodo dei Pagamenti environment, in particular on PSP (if that search filter is defined).
+ The result of the query is paginated and contains all the metadata needed for pagination purposes.
+ """)
@APIResponses(
value = {
@APIResponse(
@@ -139,17 +140,17 @@ PaginatedFlowsResponse getAllPublishedFlows(
summary = "Get single flow by creditor institution, searching by name and revision",
description =
"""
-This API permits to search a single flows for a specific creditor institution.
-In order to do so, it is required to add the following search filters:
- - Creditor institution identifier: for filtering by specific organization
- - PSP identifier: for filtering by flow-related PSP
- - Flow name: for filtering by specific instance of the flow
- - Revision: for filtering by flow revision
+ This API permits to search a single flows for a specific creditor institution.
+ In order to do so, it is required to add the following search filters:
+ - Creditor institution identifier: for filtering by specific organization
+ - PSP identifier: for filtering by flow-related PSP
+ - Flow name: for filtering by specific instance of the flow
+ - Revision: for filtering by flow revision
-Before executing the query, the search filters are validated against entities configured for
-Nodo dei Pagamenti environment, in particular on creditor institution and PSP. Also,
-the name of the flow is validated against a specific standard format.
-""")
+ Before executing the query, the search filters are validated against entities configured for
+ Nodo dei Pagamenti environment, in particular on creditor institution and PSP. Also,
+ the name of the flow is validated against a specific standard format.
+ """)
@APIResponses(
value = {
@APIResponse(
@@ -230,18 +231,18 @@ SingleFlowResponse getSinglePublishedFlow(
"Get all payments of single flow by creditor institution, searching by name and revision",
description =
"""
-This API permits to search all the payments of single flows for a specific creditor institution,
-formatted in a paginated view. In order to do so, it is required to add the following search filters:
- - Creditor institution identifier: for filtering by specific organization
- - PSP identifier: for filtering by flow-related PSP
- - Flow name: for filtering by specific instance of the flow
- - Revision: for filtering by flow revision
+ This API permits to search all the payments of single flows for a specific creditor institution,
+ formatted in a paginated view. In order to do so, it is required to add the following search filters:
+ - Creditor institution identifier: for filtering by specific organization
+ - PSP identifier: for filtering by flow-related PSP
+ - Flow name: for filtering by specific instance of the flow
+ - Revision: for filtering by flow revision
-Before executing the query, the search filters are validated against entities configured for
-Nodo dei Pagamenti environment, in particular on creditor institution and PSP. Also,
-the name of the flow is validated against a specific standard format.
-The result of the query is paginated and contains all the metadata needed for pagination purposes.
-""")
+ Before executing the query, the search filters are validated against entities configured for
+ Nodo dei Pagamenti environment, in particular on creditor institution and PSP. Also,
+ the name of the flow is validated against a specific standard format.
+ The result of the query is paginated and contains all the metadata needed for pagination purposes.
+ """)
@APIResponses(
value = {
@APIResponse(
diff --git a/src/main/java/it/gov/pagopa/fdr/repository/FdrFlowRepository.java b/src/main/java/it/gov/pagopa/fdr/repository/FdrFlowRepository.java
index a338edc9..a8500d4b 100644
--- a/src/main/java/it/gov/pagopa/fdr/repository/FdrFlowRepository.java
+++ b/src/main/java/it/gov/pagopa/fdr/repository/FdrFlowRepository.java
@@ -14,8 +14,10 @@
import it.gov.pagopa.fdr.util.common.StringUtil;
import jakarta.enterprise.context.ApplicationScoped;
import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
+import org.eclipse.microprofile.faulttolerance.Retry;
@ApplicationScoped
public class FdrFlowRepository extends Repository {
@@ -45,10 +47,11 @@ public class FdrFlowRepository extends Repository {
+ " and receiver.organization_id = :organizationId"
+ " and status != 'PUBLISHED'";
- public static final String QUERY_GET_PUBLISHED_BY_PSP_AND_NAME =
- "sender.psp_id = :pspId and name = :flowName and status = 'PUBLISHED'";
+ public static final String QUERY_GET_LAST_PUBLISHED_BY_PSP_AND_NAME =
+ "sender.psp_id = :pspId and name = :flowName and status = 'PUBLISHED' and is_latest ="
+ + " :isLatest";
- public RepositoryPagedResult findPublishedByOrganizationIdAndOptionalPspId(
+ public RepositoryPagedResult findLatestPublishedByOrganizationIdAndOptionalPspId(
String organizationId, String pspId, Instant publishedGt, int pageNumber, int pageSize) {
Parameters parameters = new Parameters();
@@ -73,6 +76,10 @@ public RepositoryPagedResult findPublishedByOrganizationIdAndOpti
// setting mandatory field: flow status
queryBuilder.add("status = :status");
parameters.and("status", FlowStatusEnum.PUBLISHED);
+
+ // setting mandatory field: is_latest flag as true
+ queryBuilder.add("is_latest = :isLatest");
+ parameters.and("isLatest", true);
String queryString = String.join(" and ", queryBuilder);
Page page = Page.of(pageNumber - 1, pageSize);
@@ -137,14 +144,15 @@ public FdrFlowEntity findPublishedByOrganizationIdAndPspIdAndName(
.orElse(null);
}
- public FdrFlowEntity findPublishedByPspIdAndName(String pspId, String flowName) {
+ public FdrFlowEntity findLastPublishedByPspIdAndName(String pspId, String flowName) {
Parameters parameters = new Parameters();
parameters.and("pspId", pspId);
parameters.and("flowName", flowName);
+ parameters.and("isLatest", true);
return FdrFlowEntity.findByQuery(
- FdrFlowRepository.QUERY_GET_PUBLISHED_BY_PSP_AND_NAME, parameters)
+ FdrFlowRepository.QUERY_GET_LAST_PUBLISHED_BY_PSP_AND_NAME, parameters)
.project(FdrFlowEntity.class)
.firstResultOptional()
.orElse(null);
@@ -230,11 +238,27 @@ public FdrFlowIdProjection findUnpublishedIdByPspIdAndNameAndOrganization(
.orElse(null);
}
+ public void updateLastPublishedAsNotLatest(String pspId, String flowName) {
+
+ FdrFlowEntity entity = findLastPublishedByPspIdAndName(pspId, flowName);
+ if (entity != null) {
+ entity.setIsLatest(false);
+ updateEntity(entity);
+ }
+ }
+
public void createEntity(FdrFlowEntity entity) {
entity.setTimestamp(Instant.now());
entity.persist();
}
+ // https://quarkus.io/guides/smallrye-fault-tolerance
+ @Retry(
+ delay = 1000,
+ maxRetries = -1,
+ maxDuration = 1,
+ durationUnit = ChronoUnit.MINUTES,
+ retryOn = Exception.class)
public void updateEntity(FdrFlowEntity entity) {
entity.setTimestamp(Instant.now());
entity.update();
diff --git a/src/main/java/it/gov/pagopa/fdr/repository/entity/flow/FdrFlowEntity.java b/src/main/java/it/gov/pagopa/fdr/repository/entity/flow/FdrFlowEntity.java
index cbc0d583..c650c140 100644
--- a/src/main/java/it/gov/pagopa/fdr/repository/entity/flow/FdrFlowEntity.java
+++ b/src/main/java/it/gov/pagopa/fdr/repository/entity/flow/FdrFlowEntity.java
@@ -32,6 +32,9 @@ public class FdrFlowEntity extends PanacheMongoEntity {
private Instant published;
+ @BsonProperty("is_latest")
+ private Boolean isLatest;
+
@BsonProperty("tot_amount")
private Double totAmount;
diff --git a/src/main/java/it/gov/pagopa/fdr/service/FlowService.java b/src/main/java/it/gov/pagopa/fdr/service/FlowService.java
index 4ac8a4b1..cdd37466 100644
--- a/src/main/java/it/gov/pagopa/fdr/service/FlowService.java
+++ b/src/main/java/it/gov/pagopa/fdr/service/FlowService.java
@@ -23,6 +23,7 @@
import it.gov.pagopa.fdr.util.error.exception.common.AppException;
import it.gov.pagopa.fdr.util.error.exception.persistence.PersistenceFailureException;
import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.transaction.Transactional;
import java.time.Instant;
import java.util.concurrent.CompletableFuture;
import org.bson.types.ObjectId;
@@ -82,7 +83,7 @@ public PaginatedFlowsResponse getPaginatedPublishedFlowsForCI(FindFlowsByFilters
SemanticValidator.validateGetPaginatedFlowsRequestForOrganizations(configData, args);
RepositoryPagedResult paginatedResult =
- this.flowRepository.findPublishedByOrganizationIdAndOptionalPspId(
+ this.flowRepository.findLatestPublishedByOrganizationIdAndOptionalPspId(
organizationId, pspId, args.getPublishedGt(), (int) pageNumber, (int) pageSize);
log.debugf(
"Found [%s] entities in [%s] pages. Mapping data to final response.",
@@ -245,7 +246,8 @@ public GenericResponse createEmptyFlow(String pspId, String flowName, CreateFlow
}
// retrieve the last published flow, in order to take its revision and increment it
- FdrFlowEntity lastPublishedFlow = flowRepository.findPublishedByPspIdAndName(pspId, flowName);
+ FdrFlowEntity lastPublishedFlow =
+ flowRepository.findLastPublishedByPspIdAndName(pspId, flowName);
Long revision = lastPublishedFlow != null ? (lastPublishedFlow.getRevision() + 1) : 1L;
// finally, persist the newly generated entity
@@ -294,13 +296,7 @@ public GenericResponse publishFlow(String pspId, String flowName, boolean isInte
// check if retrieved flow can be published
SemanticValidator.validatePublishingFlow(publishingFlow);
-
- // update the publishing flow in order to set its status to PUBLISHED
- Instant now = Instant.now();
- publishingFlow.setUpdated(now);
- publishingFlow.setPublished(now);
- publishingFlow.setStatus(FlowStatusEnum.PUBLISHED);
- this.flowRepository.updateEntity(publishingFlow);
+ publishNewRevision(pspId, flowName, publishingFlow);
// TODO do this in transactional way
// FdrFlowToHistoryEntity flowToHistoryEntity = flowMapper.toEntity(publishingFlow,
@@ -358,4 +354,18 @@ private void deleteFlowPaymentsInAsync(ObjectId flowObjectId) {
return null;
});
}
+
+ @Transactional(rollbackOn = Exception.class)
+ public void publishNewRevision(String pspId, String flowName, FdrFlowEntity publishingFlow) {
+
+ // update the publishing flow in order to set its status to PUBLISHED
+ Instant now = Instant.now();
+ publishingFlow.setUpdated(now);
+ publishingFlow.setPublished(now);
+ publishingFlow.setIsLatest(true);
+ publishingFlow.setStatus(FlowStatusEnum.PUBLISHED);
+
+ this.flowRepository.updateLastPublishedAsNotLatest(pspId, flowName);
+ this.flowRepository.updateEntity(publishingFlow);
+ }
}