diff --git a/.env.sample b/.env.sample
index c03b41f..773468e 100644
--- a/.env.sample
+++ b/.env.sample
@@ -9,4 +9,7 @@ NODO_HOST=http://localhost:8086/nodo-per-pa/v1
PAA_ID_INTERMEDIARIO=PAA_ID_INTERMEDIARIO
PAA_STAZIONE_INT=PAA_STAZIONE_INT
PAA_PASSWORD=PAA_PASSWORD
-NCRON_SCHEDULE_BATCH=*/45 * * * * *
\ No newline at end of file
+NCRON_SCHEDULE_BATCH=*/45 * * * * *
+GPD_BASE_PATH=https://api.dev.platform.pagopa.it/gpd/api/v2
+GPD_SUBKEY=GPD_SUBKEY
+FDR_EVENTHUB_CONN_STRING=FDR_EVENTHUB_CONN_STRING
\ No newline at end of file
diff --git a/.identity/00_data.tf b/.identity/00_data.tf
index 836e357..a39c99f 100644
--- a/.identity/00_data.tf
+++ b/.identity/00_data.tf
@@ -1,12 +1,3 @@
-data "azurerm_resource_group" "dashboards" {
- name = "dashboards"
-}
-
-data "azurerm_kubernetes_cluster" "aks" {
- name = local.aks_cluster.name
- resource_group_name = local.aks_cluster.resource_group_name
-}
-
data "github_organization_teams" "all" {
root_teams_only = true
summary_only = true
@@ -42,13 +33,13 @@ data "azurerm_key_vault_secret" "key_vault_integration_test_subkey" {
key_vault_id = data.azurerm_key_vault.key_vault.id
}
-data "azurerm_key_vault_secret" "flow_sa_connection_string" {
- name = "flows-sa-${var.env_short}-connection-string"
- key_vault_id = data.azurerm_key_vault.domain_key_vault.id
-}
-
-
data "azurerm_user_assigned_identity" "identity_cd_01"{
name = "${local.prefix}-${var.env_short}-${local.domain}-01-github-cd-identity"
resource_group_name = "${local.prefix}-${var.env_short}-identity-rg"
-}
\ No newline at end of file
+}
+
+
+data "azurerm_key_vault_secret" "gpd_subkey" {
+ name = "gpd-subkey-for-reporting"
+ key_vault_id = data.azurerm_key_vault.domain_key_vault.id
+}
diff --git a/.identity/03_github_environment.tf b/.identity/03_github_environment.tf
index f4e2d1a..92720f7 100644
--- a/.identity/03_github_environment.tf
+++ b/.identity/03_github_environment.tf
@@ -25,15 +25,14 @@ locals {
"TENANT_ID" : data.azurerm_client_config.current.tenant_id,
"SUBSCRIPTION_ID" : data.azurerm_subscription.current.subscription_id,
"API_SUBSCRIPTION_KEY" : data.azurerm_key_vault_secret.key_vault_integration_test_subkey.value,
- "FLOW_SA_CONNECTION_STRING": data.azurerm_key_vault_secret.flow_sa_connection_string.value
+ "GPD_SUBKEY": data.azurerm_key_vault_secret.gpd_subkey.value
}
env_variables = {
"CONTAINER_APP_ENVIRONMENT_NAME" : local.container_app_environment.name,
"CONTAINER_APP_ENVIRONMENT_RESOURCE_GROUP_NAME" : local.container_app_environment.resource_group,
"CLUSTER_NAME" : local.aks_cluster.name,
"CLUSTER_RESOURCE_GROUP" : local.aks_cluster.resource_group_name,
- "NAMESPACE" : local.domain,
- "REPORTING_BATCH_QUEUE": "pagopa${var.env_short}flowsaqueueorg"
+ "NAMESPACE" : local.domain
}
repo_secrets = {
"SONAR_TOKEN" : data.azurerm_key_vault_secret.key_vault_sonar.value,
diff --git a/.identity/env/dev/terraform.tfvars b/.identity/env/dev/terraform.tfvars
index c07a721..68c96d2 100644
--- a/.identity/env/dev/terraform.tfvars
+++ b/.identity/env/dev/terraform.tfvars
@@ -8,4 +8,4 @@ tags = {
Owner = "pagoPA"
Source = "https://github.com/pagopa/pagopa-gpd-reporting-analysis"
CostCenter = "TS310 - PAGAMENTI & SERVIZI"
-}
+}
\ No newline at end of file
diff --git a/.identity/env/prod/terraform.tfvars b/.identity/env/prod/terraform.tfvars
index 5b0baed..2cbc019 100644
--- a/.identity/env/prod/terraform.tfvars
+++ b/.identity/env/prod/terraform.tfvars
@@ -8,4 +8,4 @@ tags = {
Owner = "pagoPA"
Source = "https://github.com/pagopa/pagopa-gpd-reporting-analysis"
CostCenter = "TS310 - PAGAMENTI & SERVIZI"
-}
+}
\ No newline at end of file
diff --git a/.identity/env/uat/terraform.tfvars b/.identity/env/uat/terraform.tfvars
index f978523..7a31828 100644
--- a/.identity/env/uat/terraform.tfvars
+++ b/.identity/env/uat/terraform.tfvars
@@ -8,4 +8,4 @@ tags = {
Owner = "pagoPA"
Source = "https://github.com/pagopa/pagopa-gpd-reporting-analysis"
CostCenter = "TS310 - PAGAMENTI & SERVIZI"
-}
+}
\ No newline at end of file
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0d2e1f8..878e02e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -4,8 +4,8 @@
# more info https://docs.gitguardian.com/internal-repositories-monitoring/integrations/git_hooks/pre_commit
repos:
- repo: https://github.com/gitguardian/ggshield
- rev: v1.11.0
+ rev: v1.40.0
hooks:
- id: ggshield
language_version: python3
- stages: [ commit ]
+ stages: [ pre-commit ]
diff --git a/host.json b/host.json
index 395f9a4..d688bdb 100644
--- a/host.json
+++ b/host.json
@@ -12,14 +12,9 @@
"logging": {
"fileLoggingMode": "debugOnly",
"logLevel": {
- "default": "None",
- "Host.Results": "Error",
- "Function.GetFlow": "Warning",
- "Function.GetFlowList": "Warning",
- "Microsoft": "Information",
- "Worker": "Information",
- "Host.Aggregator": "Error",
- "Host": "Error"
+ "Function.GetFlow": "Information",
+ "Function.GetFlowList": "Information",
+ "Function.GpdReportingSync": "Information"
},
"applicationInsights": {
"samplingSettings": {
diff --git a/local.settings.json.example b/local.settings.json.example
index ba7fc1c..e553a8c 100644
--- a/local.settings.json.example
+++ b/local.settings.json.example
@@ -13,6 +13,9 @@
"NODO_HOST": "http://localhost:8081/nodo-per-pa/v1",
"PAA_ID_INTERMEDIARIO":"PAA_ID_INTERMEDIARIO",
"PAA_STAZIONE_INT":"PAA_STAZIONE_INT",
- "PAA_PASSWORD":"PAA_PASSWORD"
+ "PAA_PASSWORD":"PAA_PASSWORD",
+ "GPD_BASE_PATH":"https://api.dev.platform.pagopa.it/gpd/api/v2",
+ "GPD_SUBKEY": "GPD_SUBKEY",
+ "FDR_EVENTHUB_CONN_STRING": "FDR_EVENTHUB_CONN_STRING"
}
}
diff --git a/pom.xml b/pom.xml
index eddbed2..d126547 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,6 +108,12 @@
2.3.1
+
+ com.mashape.unirest
+ unirest-java
+ 1.4.9
+
+
org.jboss.resteasy
diff --git a/src/main/java/it/gov/pagopa/reporting/GpdReportingSync.java b/src/main/java/it/gov/pagopa/reporting/GpdReportingSync.java
new file mode 100644
index 0000000..705ac16
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/reporting/GpdReportingSync.java
@@ -0,0 +1,76 @@
+package it.gov.pagopa.reporting;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.mashape.unirest.http.HttpResponse;
+import com.mashape.unirest.http.Unirest;
+import com.microsoft.azure.functions.ExecutionContext;
+import com.microsoft.azure.functions.annotation.Cardinality;
+import com.microsoft.azure.functions.annotation.EventHubTrigger;
+import com.microsoft.azure.functions.annotation.FunctionName;
+import it.gov.pagopa.reporting.model.ReportedIUVEventModel;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Azure Functions with Azure Http trigger.
+ */
+public class GpdReportingSync {
+
+ private String gpdBasePath = System.getenv("GPD_BASE_PATH");
+ private String gpdSubeKey = System.getenv("GPD_SUBKEY");
+
+
+ /**
+ * This function will be invoked by an incoming HTTP request
+ *
+ * @return
+ */
+ @FunctionName("GpdReportingSync")
+ public void run(
+ @EventHubTrigger(
+ name = "GpdReportingSyncTrigger",
+ eventHubName = "", // blank because the value is included in the connection string
+ consumerGroup = "gpd-reporting-sync",
+ connection = "FDR_EVENTHUB_CONN_STRING",
+ cardinality = Cardinality.MANY)
+ List items,
+ final ExecutionContext context) {
+
+ Logger logger = context.getLogger();
+ logger.log(Level.FINE, () -> "[GpdReportingSync] function executed at: " + LocalDateTime.now());
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+
+ for (String event : items) {
+ ReportedIUVEventModel reportedIUVEventModel;
+ try {
+ reportedIUVEventModel = objectMapper.readValue(event, ReportedIUVEventModel.class);
+ } catch (Exception e) {
+ logger.log(Level.WARNING, () -> "[GpdReportingSync] The message was ignored because it wasn't parsed correctly. msg=[" + event + "]");
+ continue;
+ }
+ gpdReport(logger, reportedIUVEventModel.getDomainId(), reportedIUVEventModel.getIuv(), String.valueOf(reportedIUVEventModel.getIdTransfer()));
+ }
+
+ }
+
+ public void gpdReport(Logger logger, String organizationId, String iuv, String transferId) {
+ try {
+ HttpResponse response = Unirest.post(gpdBasePath + "/organizations/" + organizationId + "/paymentoptions/" + iuv + "/transfers/" + transferId + "/report")
+ .header("accept", "application/json")
+ .header("ocp-apim-subscription-key", gpdSubeKey)
+ .asString();
+ if (response.getStatus() != 200) {
+ logger.log(Level.SEVERE, () -> "[GpdReportingSync] GPD client failed with status " + response.getStatus() + " body:" + response.getBody());
+ }
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, () -> "[GpdReportingSync] GPD client Exception: " + e.getLocalizedMessage());
+ }
+ }
+
+
+}
diff --git a/src/main/java/it/gov/pagopa/reporting/model/ReportedIUVEventModel.java b/src/main/java/it/gov/pagopa/reporting/model/ReportedIUVEventModel.java
new file mode 100644
index 0000000..97808de
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/reporting/model/ReportedIUVEventModel.java
@@ -0,0 +1,58 @@
+package it.gov.pagopa.reporting.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ReportedIUVEventModel {
+
+ @JsonProperty("IUV")
+ private String iuv;
+
+ @JsonProperty("IUR")
+ private String iur;
+
+ @JsonProperty("IMPORTO")
+ private BigDecimal amount;
+
+ @JsonProperty("COD_ESITO")
+ private Integer outcomeCode;
+
+ @JsonProperty("DATA_ESITO_SINGOLO_PAGAMENTO")
+ private String singlePaymentOutcomeDate;
+
+ @JsonProperty("IDSP")
+ private String idsp;
+
+ @JsonProperty("ID_FLUSSO")
+ private String flowId;
+
+ @JsonProperty("DATA_ORA_FLUSSO")
+ private String flowDateTime;
+
+ @JsonProperty("ID_DOMINIO")
+ private String domainId;
+
+ @JsonProperty("PSP")
+ private String psp;
+
+ @JsonProperty("INT_PSP")
+ private String intPsp;
+
+ @JsonProperty("UNIQUE_ID")
+ private String uniqueId;
+
+ @JsonProperty("INSERTED_TIMESTAMP")
+ private String insertedTimestamp;
+
+ @JsonProperty("ID_TRANSFER")
+ private Long idTransfer;
+}
\ No newline at end of file
diff --git a/src/main/java/it/gov/pagopa/reporting/service/FlowsService.java b/src/main/java/it/gov/pagopa/reporting/service/FlowsService.java
index 2c7156f..9238a98 100644
--- a/src/main/java/it/gov/pagopa/reporting/service/FlowsService.java
+++ b/src/main/java/it/gov/pagopa/reporting/service/FlowsService.java
@@ -55,7 +55,12 @@ public class FlowsService {
private final String fdr3BaseUrl = System.getenv("FDR3_BASE_URL");
private final String fdr1BaseUrl = System.getenv("FDR1_BASE_URL");
- private final int flowListDepth = Integer.parseInt(System.getenv("FDR3_FLOW_LIST_DEPTH"));
+ private final int flowListDepth = Integer.parseInt(deNull(System.getenv("FDR3_FLOW_LIST_DEPTH")));
+
+ private String deNull(String fdr3FlowListDepth) {
+ return fdr3FlowListDepth != null ? fdr3FlowListDepth : "0";
+ }
+
private final String listEl4Page = System.getenv("FDR3_LIST_ELEMENTS_FOR_PAGE");
public FlowsService(String storageConnectionString, String flowsTable, String containerBlob, Logger logger) {
diff --git a/src/test/java/it/gov/pagopa/reporting/GpdReportingSyncTest.java b/src/test/java/it/gov/pagopa/reporting/GpdReportingSyncTest.java
new file mode 100644
index 0000000..946464d
--- /dev/null
+++ b/src/test/java/it/gov/pagopa/reporting/GpdReportingSyncTest.java
@@ -0,0 +1,62 @@
+package it.gov.pagopa.reporting;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.microsoft.azure.functions.ExecutionContext;
+import com.microsoft.azure.functions.HttpStatus;
+import it.gov.pagopa.reporting.model.ReportedIUVEventModel;
+import it.gov.pagopa.reporting.service.FlowsService;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.verification.VerificationMode;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class GpdReportingSyncTest {
+
+ @Spy
+ GpdReportingSync function;
+
+ @Mock
+ ExecutionContext context;
+
+
+
+ @Test
+ void noMessage() {
+ Logger logger = Logger.getLogger("testlogging");
+ when(context.getLogger()).thenReturn(logger);
+
+ List messages = new ArrayList<>();
+
+ function.run(messages, context);
+
+ Mockito.verify(function, never()).gpdReport(any(), any(), any(), any());
+ }
+
+ @Test
+ void oneMessage() throws JsonProcessingException {
+ Logger logger = Logger.getLogger("testlogging");
+ when(context.getLogger()).thenReturn(logger);
+
+ List messages = new ArrayList<>();
+ ReportedIUVEventModel msg = new ReportedIUVEventModel();
+ var mapper = new ObjectMapper();
+ messages.add(mapper.writeValueAsString(msg));
+
+ function.run(messages, context);
+
+ Mockito.verify(function, times(1)).gpdReport(any(), any(), any(), any());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/it/gov/pagopa/reporting/service/FlowServiceIntegrationTest.java b/src/test/java/it/gov/pagopa/reporting/service/FlowServiceIntegrationTest.java
index 8149807..9e30fab 100644
--- a/src/test/java/it/gov/pagopa/reporting/service/FlowServiceIntegrationTest.java
+++ b/src/test/java/it/gov/pagopa/reporting/service/FlowServiceIntegrationTest.java
@@ -51,7 +51,7 @@ class FlowServiceIntegrationTest {
@Test
void getByOrganization_noFlowDate() {
flowsService = spy(new FlowsService(storageConnectionString, flowsTable, containerBlob, logger));
- String organizationId = "90000000000";
+ String organizationId = "90000000000";
List flows = null;
try {
createTable();
@@ -65,7 +65,7 @@ void getByOrganization_noFlowDate() {
@Test
void getByOrganization_withFlowDate() {
flowsService = spy(new FlowsService(storageConnectionString, flowsTable, containerBlob, logger));
- String organizationId = "90000000000";
+ String organizationId = "90000000000";
List flows = null;
try {
createTable();
@@ -80,7 +80,7 @@ void getByOrganization_withFlowDate() {
void getByFlow() throws Exception {
flowsService = spy(new FlowsService(storageConnectionString, flowsTable, containerBlob, logger));
- String organizationId = "idPa";
+ String organizationId = "idPa";
String flowId = "idFlow";
String flowDate = "dataOra";
String data = null;
@@ -106,7 +106,7 @@ void getByFlow() throws Exception {
void getByFlow_KO() {
flowsService = spy(new FlowsService(storageConnectionString, flowsTable, containerBlob, logger));
- String organizationId = "idPa";
+ String organizationId = "idPa";
String flowId = "idFlowKO";
String flowDate = "dataOra";
String data = null;
@@ -123,7 +123,7 @@ void getByFlow_KO() {
try {
data = flowsService.getByFlow(organizationId, flowId, flowDate);
assertNull(data);
- } catch(Exception e) {
+ } catch (Exception e) {
assertNull(data);
} finally {
blobServiceClient.deleteBlobContainer(containerBlob);