Repository: pagopa/p4pa-payhub-activities
Pull request #169: feat: P4ADEV-2343 sync ingested dp impl
Author: login: Benedetta-fabbri
Labels: name: released
Created: 2025-03-14T10:53:42Z | Merged: 2025-03-14T15:13:46Z

#### Description
<!--- Please always add a PR description as if nobody knows anything about the context these changes come from. -->
<!--- Even if we are all from our internal team, we may not be on the same page. -->
<!--- Write this PR as you were contributing to a public OSS project, where nobody knows you and you have to earn their trust. -->
<!--- This will improve our projects in the long run! Thanks. -->

#### List of Changes
<!--- Describe your changes in detail -->

#### Motivation and Context
<!--- Why is this change required? What problem does it solve? -->

#### How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, tests ran to see how -->
<!--- your change affects other areas of the code, etc. -->
- Pre-Deploy Test
    - [ ] Unit
    - [ ] Integration (Narrow)
- Post-Deploy Test
    - [ ] Isolated Microservice
    - [ ] Broader Integration
    - [ ] Acceptance
    - [ ] Performance & Load

#### Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

- [ ] PATCH - Bug fix (backwards compatible bug fixes)
- [ ] MINOR - New feature (add functionality in a backwards compatible manner)
- [ ] MAJOR - Breaking change (fix or feature that would cause existing functionality to not work as expected)

#### Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.



Diff:
diff --git a/build.gradle.kts b/build.gradle.kts
index b843b0381..c7a71b554 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -90,6 +90,7 @@ dependencies {
 	implementation("org.mapstruct:mapstruct:$mapStructVersion")
 	// openApi
 	implementation("org.openapitools:jackson-databind-nullable:$openApiToolsVersion")
+	implementation("org.springframework.data:spring-data-commons")
 	//mail
 	implementation("org.springframework.boot:spring-boot-starter-mail")
 	implementation("org.springframework.retry:spring-retry")
diff --git a/gradle.lockfile b/gradle.lockfile
index b3950890f..c59ad0a6f 100644
--- a/gradle.lockfile
+++ b/gradle.lockfile
@@ -84,6 +84,7 @@ org.springframework.boot:spring-boot-starter-tomcat:3.4.3=compileClasspath
 org.springframework.boot:spring-boot-starter-web:3.4.3=compileClasspath
 org.springframework.boot:spring-boot-starter:3.4.3=compileClasspath
 org.springframework.boot:spring-boot:3.4.3=compileClasspath
+org.springframework.data:spring-data-commons:3.4.3=compileClasspath
 org.springframework.retry:spring-retry:2.0.11=compileClasspath
 org.springframework:spring-aop:6.2.3=compileClasspath
 org.springframework:spring-beans:6.2.3=compileClasspath
diff --git a/src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java
new file mode 100644
index 000000000..063b68099
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java
@@ -0,0 +1,63 @@
+package it.gov.pagopa.payhub.activities.activity.ingestionflow.debtposition;
+
+import it.gov.pagopa.payhub.activities.connector.debtposition.DebtPositionService;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Lazy
+@Service
+public class SynchronizeIngestedDebtPositionActivityImpl implements SynchronizeIngestedDebtPositionActivity {
+
+    private final DebtPositionService debtPositionService;
+    private final Integer pageSize;
+
+    private static final List<String> DEFAULT_ORDERING = List.of("debtPositionId,asc");
+
+    public SynchronizeIngestedDebtPositionActivityImpl(DebtPositionService debtPositionService,
+                                                       @Value("${query-limits.debt-positions.size}") Integer pageSize) {
+        this.debtPositionService = debtPositionService;
+        this.pageSize = pageSize;
+    }
+
+    @Override
+    public String synchronizeIngestedDebtPosition(Long ingestionFlowFileId) {
+        log.info("Synchronizing all debt positions related to ingestion flow file id {}", ingestionFlowFileId);
+
+        StringBuilder errors = new StringBuilder();
+
+        int currentPage = 0;
+        boolean hasMorePages = true;
+
+        while (hasMorePages) {
+            PagedDebtPositions pagedDebtPositions = debtPositionService.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId,
+                    currentPage,
+                    pageSize,
+                    DEFAULT_ORDERING);
+
+            log.info("Synchronizing page {} of {} retrieved searching debt positions related to ingestionFlowFileId {} (totalElements {})",
+                    currentPage, pagedDebtPositions.getTotalPages(), pagedDebtPositions.getTotalElements(), ingestionFlowFileId);
+
+            pagedDebtPositions.getContent().forEach(debtPosition -> {
+                try {
+                    // TODO invoke workflow sync and add any error (P4ADEV-2344)
+                    // TODO invoke workflow status (P4ADEV-2345)
+                } catch (Exception e) {
+                    log.error("Error synchronizing debt position with id {} and iupdOrg {}: {}", debtPosition.getDebtPositionId(), debtPosition.getIupdOrg(), e.getMessage());
+                    errors.append("Error on debt position with iupdOrg " + debtPosition.getIupdOrg() + ": " + e.getMessage() + " \n");
+                }
+            });
+
+            currentPage++;
+            hasMorePages = currentPage < pagedDebtPositions.getTotalPages();
+        }
+
+        log.info("Synchronization of all debt positions related to ingestion flow file id {} completed", ingestionFlowFileId);
+        return errors.toString();
+    }
+}
diff --git a/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionService.java b/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionService.java
index d55d3e554..eae2b9f38 100644
--- a/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionService.java
+++ b/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionService.java
@@ -3,8 +3,10 @@
 import it.gov.pagopa.pu.debtposition.dto.generated.DebtPositionDTO;
 import it.gov.pagopa.pu.debtposition.dto.generated.InstallmentSynchronizeDTO;
 import it.gov.pagopa.pu.debtposition.dto.generated.IupdSyncStatusUpdateDTO;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
 
 import java.time.LocalDate;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -36,4 +38,6 @@ public interface DebtPositionService {
      * @return the workflow ID if a workflow is triggered, otherwise null.
      */
     String installmentSynchronize(DebtPositionDTO.DebtPositionOriginEnum origin, InstallmentSynchronizeDTO installmentSynchronizeDTO, Boolean massive, String operatorUserId);
+
+    PagedDebtPositions getDebtPositionsByIngestionFlowFileId(Long ingestionFlowFileId, Integer page, Integer size, List<String> sort);
 }
diff --git a/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionServiceImpl.java b/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionServiceImpl.java
index e3b8a03ab..c876718aa 100644
--- a/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionServiceImpl.java
+++ b/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionServiceImpl.java
@@ -6,10 +6,12 @@
 import it.gov.pagopa.pu.debtposition.dto.generated.DebtPositionDTO;
 import it.gov.pagopa.pu.debtposition.dto.generated.InstallmentSynchronizeDTO;
 import it.gov.pagopa.pu.debtposition.dto.generated.IupdSyncStatusUpdateDTO;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDate;
+import java.util.List;
 import java.util.Map;
 
 @Lazy
@@ -43,4 +45,10 @@ public String installmentSynchronize(DebtPositionDTO.DebtPositionOriginEnum orig
         String accessToken = authnService.getAccessToken();
         return debtPositionClient.installmentSynchronize(accessToken, origin, installmentSynchronizeDTO, massive, operatorUserId);
     }
+
+    @Override
+    public PagedDebtPositions getDebtPositionsByIngestionFlowFileId(Long ingestionFlowFileId, Integer page, Integer size, List<String> sort) {
+        String accessToken = authnService.getAccessToken();
+        return debtPositionClient.getDebtPositionsByIngestionFlowFileId(accessToken, ingestionFlowFileId, page, size, sort);
+    }
 }
diff --git a/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/client/DebtPositionClient.java b/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/client/DebtPositionClient.java
index be3ffe5d2..e466c55aa 100644
--- a/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/client/DebtPositionClient.java
+++ b/src/main/java/it/gov/pagopa/payhub/activities/connector/debtposition/client/DebtPositionClient.java
@@ -4,10 +4,12 @@
 import it.gov.pagopa.pu.debtposition.dto.generated.DebtPositionDTO;
 import it.gov.pagopa.pu.debtposition.dto.generated.InstallmentSynchronizeDTO;
 import it.gov.pagopa.pu.debtposition.dto.generated.IupdSyncStatusUpdateDTO;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
 import java.util.Map;
 
 @Lazy
@@ -35,4 +37,8 @@ public String installmentSynchronize(String accessToken, DebtPositionDTO.DebtPos
         return response.getHeaders().getFirst("x-workflow-id");
     }
 
+    public PagedDebtPositions getDebtPositionsByIngestionFlowFileId(String accessToken, Long ingestionFlowFileId, Integer page, Integer size, List<String> sort){
+        return debtPositionApisHolder.getDebtPositionApi(accessToken).getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId, page, size, sort);
+    }
+
 }
diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml
index e4e7b98e3..d9e5c49ea 100644
--- a/src/main/resources/config/application.yml
+++ b/src/main/resources/config/application.yml
@@ -17,7 +17,6 @@ ingestion-flow-files:
       max-waiting-minutes: 5
       retry-delays-ms: 1000
 
-
 mail:
   sender-address: "\${MAIL_SENDER_ADDRESS:piattaforma-unitaria@noreply.com}"
 
@@ -100,4 +99,10 @@ rest:
     base-url: "\${WORKFLOW_HUB_BASE_URL:http://localhost:8080}"
     max-attempts: "\${WORKFLOW_HUB_MAX_ATTEMPTS:3}" # It's counting also the first attempt
     wait-time-millis: "\${WORKFLOW_HUB_WAIT_TIME_MILLIS:500}"
-    print-body-when-error: "\${WORKFLOW_HUB_PRINT_BODY_WHEN_ERROR:true}"
\ No newline at end of file
+    print-body-when-error: "\${WORKFLOW_HUB_PRINT_BODY_WHEN_ERROR:true}"
+
+query-limits:
+  default:
+    size: "\${DEFAULT_PAGE_SIZE:1000}"
+  debt-positions:
+    size: "\${DEBT_POSITIONS_PAGE_SIZE:\${query-limits.default.size}}"
diff --git a/src/test/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityTest.java b/src/test/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityTest.java
new file mode 100644
index 000000000..1a9b86df9
--- /dev/null
+++ b/src/test/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityTest.java
@@ -0,0 +1,68 @@
+package it.gov.pagopa.payhub.activities.activity.ingestionflow.debtposition;
+
+import it.gov.pagopa.payhub.activities.connector.debtposition.DebtPositionService;
+import it.gov.pagopa.pu.debtposition.dto.generated.DebtPositionDTO;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.List;
+
+import static it.gov.pagopa.payhub.activities.util.faker.DebtPositionFaker.buildDebtPositionDTO;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@ExtendWith(MockitoExtension.class)
+class SynchronizeIngestedDebtPositionActivityTest {
+
+    @Mock
+    private DebtPositionService debtPositionServiceMock;
+    private static final Integer PAGE_SIZE = 2;
+    private static final List<String> DEFAULT_ORDERING = List.of("debtPositionId,asc");
+
+    private SynchronizeIngestedDebtPositionActivity activity;
+
+    @BeforeEach
+    void setUp() {
+        activity = new SynchronizeIngestedDebtPositionActivityImpl(
+                debtPositionServiceMock, PAGE_SIZE
+        );
+    }
+
+    @Test
+    void testSynchronizeIngestedDebtPositionWithoutErrors(){
+        Long ingestionFlowFileId = 1L;
+        DebtPositionDTO debtPosition1 = buildDebtPositionDTO();
+        DebtPositionDTO debtPosition2 = buildDebtPositionDTO();
+        DebtPositionDTO debtPosition3 = buildDebtPositionDTO();
+        DebtPositionDTO debtPosition4 = buildDebtPositionDTO();
+
+        PagedDebtPositions pagedDebtPositionsFirstPage = PagedDebtPositions.builder()
+                .content(List.of(debtPosition1, debtPosition2))
+                .size(2L)
+                .totalPages(2L)
+                .totalElements(4L)
+                .number(0L)
+                .build();
+
+        PagedDebtPositions pagedDebtPositionsSecondPage = PagedDebtPositions.builder()
+                .content(List.of(debtPosition3, debtPosition4))
+                .size(2L)
+                .totalPages(2L)
+                .totalElements(4L)
+                .number(1L)
+                .build();
+
+        Mockito.when(debtPositionServiceMock.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId, 0, PAGE_SIZE, DEFAULT_ORDERING))
+                .thenReturn(pagedDebtPositionsFirstPage);
+        Mockito.when(debtPositionServiceMock.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId, 1, PAGE_SIZE, DEFAULT_ORDERING))
+                .thenReturn(pagedDebtPositionsSecondPage);
+
+        String result = activity.synchronizeIngestedDebtPosition(ingestionFlowFileId);
+
+        assertEquals("", result);
+    }
+}
diff --git a/src/test/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionServiceTest.java b/src/test/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionServiceTest.java
index aa7ee6781..7cf95b34b 100644
--- a/src/test/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionServiceTest.java
+++ b/src/test/java/it/gov/pagopa/payhub/activities/connector/debtposition/DebtPositionServiceTest.java
@@ -2,10 +2,7 @@
 
 import it.gov.pagopa.payhub.activities.connector.auth.AuthnService;
 import it.gov.pagopa.payhub.activities.connector.debtposition.client.DebtPositionClient;
-import it.gov.pagopa.pu.debtposition.dto.generated.DebtPositionDTO;
-import it.gov.pagopa.pu.debtposition.dto.generated.InstallmentDTO;
-import it.gov.pagopa.pu.debtposition.dto.generated.InstallmentSynchronizeDTO;
-import it.gov.pagopa.pu.debtposition.dto.generated.IupdSyncStatusUpdateDTO;
+import it.gov.pagopa.pu.debtposition.dto.generated.*;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -138,4 +135,24 @@ void givenInstallmentSynchronizeThenReturnsWorkflowId() {
         assertEquals(expectedWorkflowId, result);
         Mockito.verify(debtPositionClientMock).installmentSynchronize(accessToken, origin, installmentSynchronizeDTO, massive, userId);
     }
+
+    @Test
+    void givenGetDebtPositionsByIngestionFlowFileIdThenSuccess() {
+        // Given
+        String accessToken = "ACCESSTOKEN";
+        Long ingestionFlowFileId = 1L;
+        Integer page = 0;
+        Integer size = 2;
+
+        Mockito.when(authnServiceMock.getAccessToken()).thenReturn(accessToken);
+        Mockito.when(debtPositionClientMock.getDebtPositionsByIngestionFlowFileId(accessToken, ingestionFlowFileId, page, size, null))
+                .thenReturn(new PagedDebtPositions());
+
+        // When
+        PagedDebtPositions result = debtPositionService.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId, page, size, null);
+
+        // Then
+        assertEquals(new PagedDebtPositions(), result);
+    }
+
 }
diff --git a/src/test/java/it/gov/pagopa/payhub/activities/connector/debtposition/client/DebtPositionClientTest.java b/src/test/java/it/gov/pagopa/payhub/activities/connector/debtposition/client/DebtPositionClientTest.java
index cfcb1d313..384881063 100644
--- a/src/test/java/it/gov/pagopa/payhub/activities/connector/debtposition/client/DebtPositionClientTest.java
+++ b/src/test/java/it/gov/pagopa/payhub/activities/connector/debtposition/client/DebtPositionClientTest.java
@@ -5,6 +5,7 @@
 import it.gov.pagopa.pu.debtposition.dto.generated.DebtPositionDTO;
 import it.gov.pagopa.pu.debtposition.dto.generated.InstallmentSynchronizeDTO;
 import it.gov.pagopa.pu.debtposition.dto.generated.IupdSyncStatusUpdateDTO;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -115,4 +116,24 @@ void givenInstallmentSynchronizeThenOk() {
         verify(debtPositionApiMock).installmentSynchronizeWithHttpInfo(origin.getValue(), installmentSynchronizeDTO, massive);
     }
 
+    @Test
+    void givenGetDebtPositionsByIngestionFlowFileIdThenOk() {
+        // Given
+        String accessToken = "ACCESSTOKEN";
+        Long ingestionFlowFileId = 1L;
+        Integer page = 0;
+        Integer size = 2;
+
+        Mockito.when(debtPositionApisHolderMock.getDebtPositionApi(accessToken))
+                .thenReturn(debtPositionApiMock);
+        Mockito.when(debtPositionApiMock.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId, page, size, null))
+                .thenReturn(new PagedDebtPositions());
+
+        // When
+        PagedDebtPositions result = debtPositionClient.getDebtPositionsByIngestionFlowFileId(accessToken, ingestionFlowFileId, page, size, null);
+
+        // Then
+        Assertions.assertEquals(new PagedDebtPositions(), result);
+    }
+
 }
diff --git a/version b/version
index e1e86acb2..f4dca5d9a 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.75.1
+1.75.2-SNAPSHOT


Reviews:
user: login: antonioT90
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T11:45:50Z
user: login: antonioT90
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T14:35:36Z
user: login: antonioT90
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T14:48:17Z
user: login: antonioT90
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T15:13:12Z

Review comments:
diff_hunk: @@ -0,0 +1,40 @@
+package it.gov.pagopa.payhub.activities.activity.ingestionflow.debtposition;
+
+import it.gov.pagopa.payhub.activities.service.debtposition.DebtPositionSearchService;
+import it.gov.pagopa.pu.debtposition.dto.generated.DebtPositionDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Lazy
+@Service
+public class SynchronizeIngestedDebtPositionActivityImpl implements SynchronizeIngestedDebtPositionActivity {
+
+    private final DebtPositionSearchService debtPositionSearchService;
+
+    public SynchronizeIngestedDebtPositionActivityImpl(DebtPositionSearchService debtPositionSearchService) {
+        this.debtPositionSearchService = debtPositionSearchService;
+    }
+
+    @Override
+    public String synchronizeIngestedDebtPosition(Long ingestionFlowFileId) {
+        log.info("Synchronizing all debt positions related to ingestion flow file id {}", ingestionFlowFileId);
+        List<DebtPositionDTO> debtPositions = debtPositionSearchService.getAllDebtPositionsByIngestionFlowFileId(ingestionFlowFileId);
path: src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java
user: login: antonioT90
body: don't accumulate all DebtPosition, but work them page-by-page.
on each page, you should invoke the API and then wait for all WF if there is a workflowId

ps: pageSize could still be a configuration read by the service instead, as the sort configuration
created_at: 2025-03-14T11:34:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,50 @@
+package it.gov.pagopa.payhub.activities.service.debtposition;
+
+import it.gov.pagopa.payhub.activities.connector.debtposition.DebtPositionService;
+import it.gov.pagopa.pu.debtposition.dto.generated.DebtPositionDTO;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@Lazy
+@Slf4j
+public class DebtPositionSearchService {
+
+    private final DebtPositionService debtPositionService;
+    private final Integer pageSize;
+
+    public DebtPositionSearchService(DebtPositionService debtPositionService,
+                                     @Value("${debt-position-pagination.page-size}") Integer pageSize) {
+        this.debtPositionService = debtPositionService;
+        this.pageSize = pageSize;
+    }
+
+    public List<DebtPositionDTO> getAllDebtPositionsByIngestionFlowFileId(Long ingestionFlowFileId){
+        log.info("Retrieving all debt positions related to ingestion flow file id {}", ingestionFlowFileId);
+
+        List<DebtPositionDTO> debtPositions = new ArrayList<>();
+
+        int currentPage = 0;
+        boolean hasMorePages = true;
+
+        while (hasMorePages) {
+            PagedDebtPositions pagedDebtPositions = debtPositionService.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId,
+                    currentPage,
+                    pageSize,
+                    null);
path: src/main/java/it/gov/pagopa/payhub/activities/service/debtposition/DebtPositionSearchService.java
user: login: antonioT90
body: better if we sort by `debtPositionId,asc`

ps: create a constant DEFAULT_ORDERING
created_at: 2025-03-14T11:40:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -100,4 +99,7 @@ rest:
     base-url: "\${WORKFLOW_HUB_BASE_URL:http://localhost:8080}"
     max-attempts: "\${WORKFLOW_HUB_MAX_ATTEMPTS:3}" # It's counting also the first attempt
     wait-time-millis: "\${WORKFLOW_HUB_WAIT_TIME_MILLIS:500}"
-    print-body-when-error: "\${WORKFLOW_HUB_PRINT_BODY_WHEN_ERROR:true}"
\ No newline at end of file
+    print-body-when-error: "\${WORKFLOW_HUB_PRINT_BODY_WHEN_ERROR:true}"
+
+debt-position-pagination:
+  page-size: "\${DEBT_POSITIONS_PAGE_SIZE:1000}"
path: src/main/resources/config/application.yml
user: login: antonioT90
body: let's structurate in order to allow for future pagination requirements
```suggestion
query-limits:
  default:
     size: "\${DEFAULT_PAGE_SIZE:1000}"
  debt-positions:
     size: "\${DEBT_POSITIONS_PAGE_SIZE:\${query-limits.default.size}}"
```
created_at: 2025-03-14T11:44:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,64 @@
+package it.gov.pagopa.payhub.activities.activity.ingestionflow.debtposition;
+
+import it.gov.pagopa.payhub.activities.connector.debtposition.DebtPositionService;
+import it.gov.pagopa.payhub.activities.exception.InvalidValueException;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Lazy
+@Service
+public class SynchronizeIngestedDebtPositionActivityImpl implements SynchronizeIngestedDebtPositionActivity {
+
+    private final DebtPositionService debtPositionService;
+    private final Integer pageSize;
+
+    private static final List<String> DEFAULT_ORDERING = List.of("debtPositionId","asc");
path: src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java
user: login: antonioT90
body: ```suggestion
    private static final List<String> DEFAULT_ORDERING = List.of("debtPositionId,asc");
```
created_at: 2025-03-14T14:31:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,64 @@
+package it.gov.pagopa.payhub.activities.activity.ingestionflow.debtposition;
+
+import it.gov.pagopa.payhub.activities.connector.debtposition.DebtPositionService;
+import it.gov.pagopa.payhub.activities.exception.InvalidValueException;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Lazy
+@Service
+public class SynchronizeIngestedDebtPositionActivityImpl implements SynchronizeIngestedDebtPositionActivity {
+
+    private final DebtPositionService debtPositionService;
+    private final Integer pageSize;
+
+    private static final List<String> DEFAULT_ORDERING = List.of("debtPositionId","asc");
+
+    public SynchronizeIngestedDebtPositionActivityImpl(DebtPositionService debtPositionService,
+                                                       @Value("${query-limits.debt-positions.size}") Integer pageSize) {
+        this.debtPositionService = debtPositionService;
+        this.pageSize = pageSize;
+    }
+
+    @Override
+    public String synchronizeIngestedDebtPosition(Long ingestionFlowFileId) {
+        log.info("Synchronizing all debt positions related to ingestion flow file id {}", ingestionFlowFileId);
+
+        StringBuilder errors = new StringBuilder();
+
+        int currentPage = 0;
+        boolean hasMorePages = true;
+
+        while (hasMorePages) {
+            PagedDebtPositions pagedDebtPositions = debtPositionService.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId,
+                    currentPage,
+                    pageSize,
+                    DEFAULT_ORDERING);
+
+            if(pagedDebtPositions == null){
+                throw new InvalidValueException("No debt positions found for the ingestion flow file with id " + ingestionFlowFileId);
+            }
path: src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java
user: login: antonioT90
body: cannot happen, let's not handle
created_at: 2025-03-14T14:32:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,64 @@
+package it.gov.pagopa.payhub.activities.activity.ingestionflow.debtposition;
+
+import it.gov.pagopa.payhub.activities.connector.debtposition.DebtPositionService;
+import it.gov.pagopa.payhub.activities.exception.InvalidValueException;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Lazy
+@Service
+public class SynchronizeIngestedDebtPositionActivityImpl implements SynchronizeIngestedDebtPositionActivity {
+
+    private final DebtPositionService debtPositionService;
+    private final Integer pageSize;
+
+    private static final List<String> DEFAULT_ORDERING = List.of("debtPositionId","asc");
+
+    public SynchronizeIngestedDebtPositionActivityImpl(DebtPositionService debtPositionService,
+                                                       @Value("${query-limits.debt-positions.size}") Integer pageSize) {
+        this.debtPositionService = debtPositionService;
+        this.pageSize = pageSize;
+    }
+
+    @Override
+    public String synchronizeIngestedDebtPosition(Long ingestionFlowFileId) {
+        log.info("Synchronizing all debt positions related to ingestion flow file id {}", ingestionFlowFileId);
+
+        StringBuilder errors = new StringBuilder();
+
+        int currentPage = 0;
+        boolean hasMorePages = true;
+
+        while (hasMorePages) {
+            PagedDebtPositions pagedDebtPositions = debtPositionService.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId,
+                    currentPage,
+                    pageSize,
+                    DEFAULT_ORDERING);
+
+            if(pagedDebtPositions == null){
+                throw new InvalidValueException("No debt positions found for the ingestion flow file with id " + ingestionFlowFileId);
+            }
+
+            pagedDebtPositions.getContent().forEach(debtPosition -> {
+                try {
+                    // TODO invoke workflow sync and add any error (P4ADEV-2344)
+                    // TODO invoke workflow status (P4ADEV-2345)
+                } catch (Exception e) {
+                    log.error("Error synchronizing debt position with id {}: {}", debtPosition.getDebtPositionId(), e.getMessage());
path: src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java
user: login: antonioT90
body: let's log also the iupdOrg, in order to easly found the log reading the errorDescription
created_at: 2025-03-14T14:34:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,59 @@
+package it.gov.pagopa.payhub.activities.activity.ingestionflow.debtposition;
+
+import it.gov.pagopa.payhub.activities.connector.debtposition.DebtPositionService;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Lazy
+@Service
+public class SynchronizeIngestedDebtPositionActivityImpl implements SynchronizeIngestedDebtPositionActivity {
+
+    private final DebtPositionService debtPositionService;
+    private final Integer pageSize;
+
+    private static final List<String> DEFAULT_ORDERING = List.of("debtPositionId,asc");
+
+    public SynchronizeIngestedDebtPositionActivityImpl(DebtPositionService debtPositionService,
+                                                       @Value("${query-limits.debt-positions.size}") Integer pageSize) {
+        this.debtPositionService = debtPositionService;
+        this.pageSize = pageSize;
+    }
+
+    @Override
+    public String synchronizeIngestedDebtPosition(Long ingestionFlowFileId) {
+        log.info("Synchronizing all debt positions related to ingestion flow file id {}", ingestionFlowFileId);
+
+        StringBuilder errors = new StringBuilder();
+
+        int currentPage = 0;
+        boolean hasMorePages = true;
+
+        while (hasMorePages) {
+            PagedDebtPositions pagedDebtPositions = debtPositionService.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId,
+                    currentPage,
+                    pageSize,
+                    DEFAULT_ORDERING);
+
path: src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java
user: login: antonioT90
body: let's log page advance:
log.info("Synchronizing page {} of {} retrieved searching debt positions related to ingestionFlowFileId {} (totalElements {})",
currentPage, pagedDebtPositions.getTotalPages(), pagedDebtPositions.getTotalElements(), ingestionFlowFileId);
created_at: 2025-03-14T14:47:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,59 @@
+package it.gov.pagopa.payhub.activities.activity.ingestionflow.debtposition;
+
+import it.gov.pagopa.payhub.activities.connector.debtposition.DebtPositionService;
+import it.gov.pagopa.pu.debtposition.dto.generated.PagedDebtPositions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Lazy
+@Service
+public class SynchronizeIngestedDebtPositionActivityImpl implements SynchronizeIngestedDebtPositionActivity {
+
+    private final DebtPositionService debtPositionService;
+    private final Integer pageSize;
+
+    private static final List<String> DEFAULT_ORDERING = List.of("debtPositionId,asc");
+
+    public SynchronizeIngestedDebtPositionActivityImpl(DebtPositionService debtPositionService,
+                                                       @Value("${query-limits.debt-positions.size}") Integer pageSize) {
+        this.debtPositionService = debtPositionService;
+        this.pageSize = pageSize;
+    }
+
+    @Override
+    public String synchronizeIngestedDebtPosition(Long ingestionFlowFileId) {
+        log.info("Synchronizing all debt positions related to ingestion flow file id {}", ingestionFlowFileId);
+
+        StringBuilder errors = new StringBuilder();
+
+        int currentPage = 0;
+        boolean hasMorePages = true;
+
+        while (hasMorePages) {
+            PagedDebtPositions pagedDebtPositions = debtPositionService.getDebtPositionsByIngestionFlowFileId(ingestionFlowFileId,
+                    currentPage,
+                    pageSize,
+                    DEFAULT_ORDERING);
+
+            pagedDebtPositions.getContent().forEach(debtPosition -> {
+                try {
+                    // TODO invoke workflow sync and add any error (P4ADEV-2344)
+                    // TODO invoke workflow status (P4ADEV-2345)
+                } catch (Exception e) {
+                    log.error("Error synchronizing debt position with id {} and iupdOrg {}: {}", debtPosition.getDebtPositionId(), debtPosition.getIupdOrg(), e.getMessage());
+                    errors.append("Error on debt position with iupdOrg " + debtPosition.getIupdOrg() + ": " + e.getMessage() + " \n");
+                }
+            });
+
+            currentPage++;
+            hasMorePages = currentPage < pagedDebtPositions.getTotalPages();
+        }
+
+        return errors.toString();
path: src/main/java/it/gov/pagopa/payhub/activities/activity/ingestionflow/debtposition/SynchronizeIngestedDebtPositionActivityImpl.java
user: login: antonioT90
body: let's log end of processing
log.info("Synchronization of all debt positions related to ingestion flow file id {} completed", ingestionFlowFileId);
created_at: 2025-03-14T14:48:08Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-03-14T14:57:32Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=pagopa_p4pa-payhub-activities&pullRequest=169) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [2 New issues](https://sonarcloud.io/project/issues?id=pagopa_p4pa-payhub-activities&pullRequest=169&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=pagopa_p4pa-payhub-activities&pullRequest=169&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=pagopa_p4pa-payhub-activities&pullRequest=169&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=pagopa_p4pa-payhub-activities&pullRequest=169&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=pagopa_p4pa-payhub-activities&pullRequest=169&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=pagopa_p4pa-payhub-activities&pullRequest=169)


author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-14T15:14:19Z
body: :tada: This PR is included in version 1.76.0 :tada:

The release is available on [GitHub release](https://github.com/pagopa/p4pa-payhub-activities/releases/tag/v1.76.0)

Your **[semantic-release](https://github.com/semantic-release/semantic-release)** bot :package::rocket:
author_association: CONTRIBUTOR