diff --git a/openapi/openapi.json b/openapi/openapi.json
index 8739dc4..eee2ec7 100644
--- a/openapi/openapi.json
+++ b/openapi/openapi.json
@@ -32,8 +32,8 @@
}
],
"responses": {
- "500": {
- "description": "Service unavailable.",
+ "200": {
+ "description": "Obtained all enrollments for the creditor institution.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -45,7 +45,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/ProblemJson"
+ "$ref": "#/components/schemas/OrganizationModelResponse"
}
}
}
@@ -61,8 +61,8 @@
}
}
},
- "200": {
- "description": "Obtained all enrollments for the creditor institution.",
+ "404": {
+ "description": "Not found the creditor institution.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -74,13 +74,13 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/OrganizationModelResponse"
+ "$ref": "#/components/schemas/ProblemJson"
}
}
}
},
- "404": {
- "description": "Not found the creditor institution.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -135,8 +135,8 @@
"required": true
},
"responses": {
- "200": {
- "description": "Request updated.",
+ "400": {
+ "description": "Malformed request.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -148,13 +148,13 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/OrganizationModelResponse"
+ "$ref": "#/components/schemas/ProblemJson"
}
}
}
},
- "500": {
- "description": "Service unavailable.",
+ "401": {
+ "description": "Wrong or missing function key.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -162,17 +162,10 @@
"type": "string"
}
}
- },
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ProblemJson"
- }
- }
}
},
- "404": {
- "description": "Not found the creditor institution.",
+ "200": {
+ "description": "Request updated.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -184,13 +177,13 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/ProblemJson"
+ "$ref": "#/components/schemas/OrganizationModelResponse"
}
}
}
},
- "401": {
- "description": "Wrong or missing function key.",
+ "404": {
+ "description": "Not found the creditor institution.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -198,10 +191,17 @@
"type": "string"
}
}
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ProblemJson"
+ }
+ }
}
},
- "400": {
- "description": "Malformed request.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -256,8 +256,8 @@
"required": true
},
"responses": {
- "500": {
- "description": "Service unavailable.",
+ "409": {
+ "description": "The organization to create already exists.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -274,8 +274,8 @@
}
}
},
- "201": {
- "description": "Request created.",
+ "400": {
+ "description": "Malformed request.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -287,13 +287,13 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/OrganizationModelResponse"
+ "$ref": "#/components/schemas/ProblemJson"
}
}
}
},
- "409": {
- "description": "The organization to create already exists.",
+ "401": {
+ "description": "Wrong or missing function key.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -301,17 +301,10 @@
"type": "string"
}
}
- },
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ProblemJson"
- }
- }
}
},
- "401": {
- "description": "Wrong or missing function key.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -319,10 +312,17 @@
"type": "string"
}
}
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ProblemJson"
+ }
+ }
}
},
- "400": {
- "description": "Malformed request.",
+ "201": {
+ "description": "Request created.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -334,7 +334,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/ProblemJson"
+ "$ref": "#/components/schemas/OrganizationModelResponse"
}
}
}
@@ -388,8 +388,8 @@
}
],
"responses": {
- "500": {
- "description": "Service unavailable.",
+ "200": {
+ "description": "Obtained single enrollment.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -401,13 +401,13 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/ProblemJson"
+ "$ref": "#/components/schemas/EnrollmentModelResponse"
}
}
}
},
- "404": {
- "description": "Not found the enroll service.",
+ "401": {
+ "description": "Wrong or missing function key.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -415,17 +415,10 @@
"type": "string"
}
}
- },
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ProblemJson"
- }
- }
}
},
- "200": {
- "description": "Obtained single enrollment.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -437,13 +430,13 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/EnrollmentModelResponse"
+ "$ref": "#/components/schemas/ProblemJson"
}
}
}
},
- "401": {
- "description": "Wrong or missing function key.",
+ "404": {
+ "description": "Not found the enroll service.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -451,6 +444,13 @@
"type": "string"
}
}
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ProblemJson"
+ }
+ }
}
}
},
@@ -500,8 +500,8 @@
"required": true
},
"responses": {
- "200": {
- "description": "Request updated.",
+ "404": {
+ "description": "Not found the creditor institution or the enroll service.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -513,13 +513,13 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/OrganizationModelResponse"
+ "$ref": "#/components/schemas/ProblemJson"
}
}
}
},
- "500": {
- "description": "Service unavailable.",
+ "400": {
+ "description": "Malformed request.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -536,8 +536,8 @@
}
}
},
- "404": {
- "description": "Not found the creditor institution or the enroll service.",
+ "401": {
+ "description": "Wrong or missing function key.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -545,17 +545,10 @@
"type": "string"
}
}
- },
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ProblemJson"
- }
- }
}
},
- "401": {
- "description": "Wrong or missing function key.",
+ "200": {
+ "description": "Request updated.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -563,10 +556,17 @@
"type": "string"
}
}
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/OrganizationModelResponse"
+ }
+ }
}
},
- "400": {
- "description": "Malformed request.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -630,8 +630,8 @@
"required": true
},
"responses": {
- "409": {
- "description": "The enrollment to the service already exists.",
+ "404": {
+ "description": "Not found the creditor institution or the enroll service.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -648,8 +648,8 @@
}
}
},
- "500": {
- "description": "Service unavailable.",
+ "400": {
+ "description": "Malformed request.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -666,8 +666,8 @@
}
}
},
- "201": {
- "description": "Request created.",
+ "401": {
+ "description": "Wrong or missing function key.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -675,17 +675,10 @@
"type": "string"
}
}
- },
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/OrganizationModelResponse"
- }
- }
}
},
- "404": {
- "description": "Not found the creditor institution or the enroll service.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -702,8 +695,8 @@
}
}
},
- "401": {
- "description": "Wrong or missing function key.",
+ "409": {
+ "description": "The enrollment to the service already exists.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -711,10 +704,17 @@
"type": "string"
}
}
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ProblemJson"
+ }
+ }
}
},
- "400": {
- "description": "Malformed request.",
+ "201": {
+ "description": "Request created.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -726,7 +726,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/ProblemJson"
+ "$ref": "#/components/schemas/OrganizationModelResponse"
}
}
}
@@ -768,8 +768,8 @@
}
],
"responses": {
- "500": {
- "description": "Service unavailable.",
+ "404": {
+ "description": "Not found the creditor institution or the enroll service.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -786,6 +786,17 @@
}
}
},
+ "401": {
+ "description": "Wrong or missing function key.",
+ "headers": {
+ "X-Request-Id": {
+ "description": "This header identifies the call",
+ "schema": {
+ "type": "string"
+ }
+ }
+ }
+ },
"200": {
"description": "Request deleted.",
"headers": {
@@ -804,8 +815,8 @@
}
}
},
- "404": {
- "description": "Not found the creditor institution or the enroll service.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -821,17 +832,6 @@
}
}
}
- },
- "401": {
- "description": "Wrong or missing function key.",
- "headers": {
- "X-Request-Id": {
- "description": "This header identifies the call",
- "schema": {
- "type": "string"
- }
- }
- }
}
},
"security": [
@@ -901,8 +901,8 @@
}
}
},
- "500": {
- "description": "Service unavailable.",
+ "400": {
+ "description": "Malformed request.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -919,8 +919,8 @@
}
}
},
- "409": {
- "description": "Conflict: duplicate debt position found.",
+ "401": {
+ "description": "Wrong or missing function key.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -928,17 +928,10 @@
"type": "string"
}
}
- },
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ProblemJson"
- }
- }
}
},
- "401": {
- "description": "Wrong or missing function key.",
+ "409": {
+ "description": "Conflict: duplicate debt position found.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -946,10 +939,17 @@
"type": "string"
}
}
+ },
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ProblemJson"
+ }
+ }
}
},
- "400": {
- "description": "Malformed request.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -995,8 +995,8 @@
"summary": "Return all services.",
"operationId": "getServices",
"responses": {
- "500": {
- "description": "Service unavailable.",
+ "200": {
+ "description": "Obtained all enrollments for the creditor institution.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -1008,7 +1008,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/ProblemJson"
+ "$ref": "#/components/schemas/OrganizationModelResponse"
}
}
}
@@ -1024,8 +1024,8 @@
}
}
},
- "200": {
- "description": "Obtained all enrollments for the creditor institution.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -1037,7 +1037,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/OrganizationModelResponse"
+ "$ref": "#/components/schemas/ProblemJson"
}
}
}
@@ -1082,8 +1082,8 @@
}
],
"responses": {
- "500": {
- "description": "Service unavailable.",
+ "200": {
+ "description": "Obtained single service details.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -1095,13 +1095,13 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/ProblemJson"
+ "$ref": "#/components/schemas/ServiceDetailModelResponse"
}
}
}
},
- "200": {
- "description": "Obtained single service details.",
+ "404": {
+ "description": "No service found.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -1113,7 +1113,7 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/ServiceDetailModelResponse"
+ "$ref": "#/components/schemas/ProblemJson"
}
}
}
@@ -1129,8 +1129,8 @@
}
}
},
- "404": {
- "description": "No service found.",
+ "500": {
+ "description": "Service unavailable.",
"headers": {
"X-Request-Id": {
"description": "This header identifies the call",
@@ -1186,6 +1186,28 @@
}
}
},
+ "ProblemJson": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "description": "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable"
+ },
+ "status": {
+ "maximum": 600,
+ "minimum": 100,
+ "type": "integer",
+ "description": "The HTTP status code generated by the origin server for this occurrence of the problem.",
+ "format": "int32",
+ "example": 200
+ },
+ "detail": {
+ "type": "string",
+ "description": "A human readable explanation specific to this occurrence of the problem.",
+ "example": "There was an error processing the request"
+ }
+ }
+ },
"EnrollmentModelResponse": {
"required": [
"iban",
@@ -1233,28 +1255,6 @@
}
}
},
- "ProblemJson": {
- "type": "object",
- "properties": {
- "title": {
- "type": "string",
- "description": "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable"
- },
- "status": {
- "maximum": 600,
- "minimum": 100,
- "type": "integer",
- "description": "The HTTP status code generated by the origin server for this occurrence of the problem.",
- "format": "int32",
- "example": 200
- },
- "detail": {
- "type": "string",
- "description": "A human readable explanation specific to this occurrence of the problem.",
- "example": "There was an error processing the request"
- }
- }
- },
"EnrollmentModel": {
"type": "object",
"properties": {
diff --git a/pom.xml b/pom.xml
index 923dc01..8fce206 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,112 +1,122 @@
- 4.0.0
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.7.0
-
-
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.0
+
+
- it.gov.pagopa
- spontaneouspayment
- 0.0.1
- Gestione Pagamenti Spontanei
- Progetto Gestione Pagamenti Spontanei
+ it.gov.pagopa
+ spontaneouspayment
+ 0.0.1
+ Gestione Pagamenti Spontanei
+ Progetto Gestione Pagamenti Spontanei
-
- 11
- 1.17.2
- 3.0.0
- 1.6.9
- 3.21.0
- 3.1.3
- 3.1.0
-
+
+ 11
+ 1.17.2
+ 3.0.0
+ 1.6.9
+ 3.21.0
+ 3.1.3
+ 3.1.0
+
-
-
- com.azure
- azure-spring-data-cosmos
- ${cosmos-data-version}
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-validation
-
-
- org.springframework.retry
- spring-retry
-
-
- org.hibernate.validator
- hibernate-validator
-
-
- org.springdoc
- springdoc-openapi-ui
- ${springdoc-version}
-
-
- org.springframework.cloud
- spring-cloud-starter-openfeign
- ${openfeign-version}
-
-
- org.modelmapper
- modelmapper
- ${modelmapper-version}
-
-
- org.springframework
- spring-context
-
-
- org.aspectj
- aspectjweaver
- compile
-
-
- org.projectlombok
- lombok
- true
-
-
- org.springframework.boot
- spring-boot-starter-test
+
+
+ com.azure
+ azure-spring-data-cosmos
+ ${cosmos-data-version}
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.retry
+ spring-retry
+
+
+ org.hibernate.validator
+ hibernate-validator
+
+
+ org.springdoc
+ springdoc-openapi-ui
+ ${springdoc-version}
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ ${openfeign-version}
+
+
+ org.modelmapper
+ modelmapper
+ ${modelmapper-version}
+
+
+ org.springframework
+ spring-context
+
+
+ org.aspectj
+ aspectjweaver
+ compile
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.testcontainers
+ azure
+ test
+
+
+ org.testcontainers
+ junit-jupiter
test
-
- com.fasterxml.jackson.datatype
- jackson-datatype-jsr310
-
-
-
-
-
- org.testcontainers
- testcontainers-bom
- ${testcontainers.version}
- pom
- import
-
-
-
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
+
+
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
diff --git a/src/main/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsService.java b/src/main/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsService.java
index 58f2dfb..20ced16 100644
--- a/src/main/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsService.java
+++ b/src/main/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsService.java
@@ -17,8 +17,12 @@
import it.gov.pagopa.spontaneouspayment.model.OrganizationModel;
import it.gov.pagopa.spontaneouspayment.repository.OrganizationRepository;
import it.gov.pagopa.spontaneouspayment.repository.ServiceRepository;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
@Service
+@AllArgsConstructor
+@NoArgsConstructor
public class EnrollmentsService {
@Autowired
diff --git a/src/test/java/it/gov/pagopa/spontaneouspayment/CosmosDBContainerTest.java b/src/test/java/it/gov/pagopa/spontaneouspayment/CosmosDBContainerTest.java
new file mode 100644
index 0000000..3de371d
--- /dev/null
+++ b/src/test/java/it/gov/pagopa/spontaneouspayment/CosmosDBContainerTest.java
@@ -0,0 +1,76 @@
+package it.gov.pagopa.spontaneouspayment;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.Rule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.rules.TemporaryFolder;
+import org.testcontainers.containers.CosmosDBEmulatorContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+import com.azure.cosmos.CosmosAsyncClient;
+import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.models.CosmosContainerResponse;
+import com.azure.cosmos.models.CosmosDatabaseResponse;
+
+@Testcontainers
+class CosmosDBContainerTest {
+
+ @Rule
+ public TemporaryFolder tempFolder= new TemporaryFolder();
+
+
+ @Container
+ private static final CosmosDBEmulatorContainer emulator = new CosmosDBEmulatorContainer(
+ DockerImageName.parse("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest"));
+
+
+
+ @BeforeEach
+ public void setUp() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
+ tempFolder.create();
+ Path keyStoreFile = tempFolder.newFile("azure-cosmos-emulator.keystore").toPath();
+ KeyStore keyStore = emulator.buildNewKeyStore();
+ keyStore.store(new FileOutputStream(keyStoreFile.toFile()), emulator.getEmulatorKey().toCharArray());
+
+ System.setProperty("javax.net.ssl.trustStore", keyStoreFile.toString());
+ System.setProperty("javax.net.ssl.trustStorePassword", emulator.getEmulatorKey());
+ System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
+ }
+
+ @Test
+ void cosmosDBEmulatorCheck() {
+
+ assertTrue(emulator.isRunning());
+
+
+
+ CosmosAsyncClient client = new CosmosClientBuilder()
+ .gatewayMode()
+ .endpointDiscoveryEnabled(false)
+ .endpoint(emulator.getEmulatorEndpoint())
+ .key(emulator.getEmulatorKey())
+ .buildAsyncClient();
+
+ CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists("Azure").block();
+
+ Assertions.assertEquals(201, databaseResponse.getStatusCode());
+ CosmosContainerResponse containerResponse = client
+ .getDatabase("Azure")
+ .createContainerIfNotExists("ServiceContainer", "/name")
+ .block();
+ Assertions.assertEquals(201, containerResponse.getStatusCode());
+ }
+}
diff --git a/src/test/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsServiceTest.java b/src/test/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsServiceTest.java
new file mode 100644
index 0000000..e2d95ac
--- /dev/null
+++ b/src/test/java/it/gov/pagopa/spontaneouspayment/service/EnrollmentsServiceTest.java
@@ -0,0 +1,471 @@
+package it.gov.pagopa.spontaneouspayment.service;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.spy;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.rules.TemporaryFolder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.testcontainers.containers.CosmosDBEmulatorContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+import com.azure.cosmos.CosmosAsyncClient;
+import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.models.CosmosContainerResponse;
+import com.azure.cosmos.models.CosmosDatabaseResponse;
+
+import it.gov.pagopa.spontaneouspayment.entity.Organization;
+import it.gov.pagopa.spontaneouspayment.entity.Service;
+import it.gov.pagopa.spontaneouspayment.entity.ServiceProperty;
+import it.gov.pagopa.spontaneouspayment.entity.ServiceRef;
+import it.gov.pagopa.spontaneouspayment.exception.AppException;
+import it.gov.pagopa.spontaneouspayment.model.EnrollmentModel;
+import it.gov.pagopa.spontaneouspayment.model.OrganizationModel;
+import it.gov.pagopa.spontaneouspayment.model.enumeration.Status;
+import it.gov.pagopa.spontaneouspayment.repository.OrganizationRepository;
+import it.gov.pagopa.spontaneouspayment.repository.ServiceRepository;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@SpringBootTest
+@Testcontainers
+class EnrollmentsServiceTest {
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ @Autowired
+ private OrganizationRepository ciRepository;
+
+ @Autowired
+ private ServiceRepository serviceRepository;
+
+ @Container
+ private static final CosmosDBEmulatorContainer emulator = new CosmosDBEmulatorContainer(
+ DockerImageName.parse("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest"));
+
+ private static EnrollmentsService enrollmentsService;
+
+ @BeforeAll
+ public void setUp() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
+
+ enrollmentsService = spy(new EnrollmentsService(ciRepository, serviceRepository));
+
+ tempFolder.create();
+ Path keyStoreFile = tempFolder.newFile("azure-cosmos-emulator.keystore").toPath();
+ KeyStore keyStore = emulator.buildNewKeyStore();
+ keyStore.store(new FileOutputStream(keyStoreFile.toFile()), emulator.getEmulatorKey().toCharArray());
+
+ System.setProperty("javax.net.ssl.trustStore", keyStoreFile.toString());
+ System.setProperty("javax.net.ssl.trustStorePassword", emulator.getEmulatorKey());
+ System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
+
+ CosmosAsyncClient client = new CosmosClientBuilder().gatewayMode().endpointDiscoveryEnabled(false)
+ .endpoint(emulator.getEmulatorEndpoint()).key(emulator.getEmulatorKey()).buildAsyncClient();
+
+ // creation of the database and containers
+ CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists("db").block();
+
+ Assertions.assertEquals(201, databaseResponse.getStatusCode());
+ CosmosContainerResponse containerResponse = client.getDatabase("db")
+ .createContainerIfNotExists("creditor_institutions", "/fiscalCode").block();
+ Assertions.assertEquals(201, containerResponse.getStatusCode());
+ containerResponse = client.getDatabase("db").createContainerIfNotExists("services", "/fiscalCode").block();
+ Assertions.assertEquals(201, containerResponse.getStatusCode());
+
+ // loading the database with test data
+ Organization ci = new Organization();
+ ci.setFiscalCode("organizationTest");
+ ci.setCompanyName("Comune di Roma");
+ ci.setStatus(Status.ENABLED);
+
+ Service s1 = new Service();
+ s1.setId("id-servizio-1");
+ s1.setTransferCategory("tassonomia-1");
+ s1.setRemittanceInformation("causale-1");
+ s1.setBasePath("base-path-1");
+ s1.setEndpoint("endpont-1");
+
+ ServiceProperty sp1 = new ServiceProperty("propName1", "number", true);
+ List properties1 = new ArrayList<>();
+ properties1.add(sp1);
+ s1.setProperties(properties1);
+
+ Service s2 = new Service();
+ s2.setId("id-servizio-2");
+ s2.setTransferCategory("tassonomia-2");
+ s2.setRemittanceInformation("causale-2");
+ s2.setBasePath("base-path-2");
+ s2.setEndpoint("endpont-2");
+
+ ServiceProperty sp2 = new ServiceProperty("propName2", "string", true);
+ List properties2 = new ArrayList<>();
+ properties2.add(sp2);
+ s2.setProperties(properties2);
+
+ Service s3 = new Service();
+ s3.setId("id-servizio-3");
+ s3.setTransferCategory("tassonomia-3");
+ s3.setRemittanceInformation("causale-3");
+ s3.setBasePath("base-path-3");
+ s3.setEndpoint("endpont-3");
+
+ ServiceProperty sp3 = new ServiceProperty("propName3", "url", true);
+ List properties3 = new ArrayList<>();
+ properties3.add(sp3);
+ s3.setProperties(properties3);
+
+ Service s4 = new Service();
+ s4.setId("id-servizio-4");
+ s4.setTransferCategory("tassonomia-4");
+ s4.setRemittanceInformation("causale-4");
+ s4.setBasePath("base-path-4");
+ s4.setEndpoint("endpont-4");
+
+ ServiceProperty sp4 = new ServiceProperty("propName4", "rule", true);
+ List properties4 = new ArrayList<>();
+ properties4.add(sp4);
+ s4.setProperties(properties4);
+
+ ServiceRef ref1 = new ServiceRef();
+ ref1.setServiceId("id-servizio-1");
+ ref1.setIban("iban-1");
+ ServiceRef ref2 = new ServiceRef();
+ ref2.setServiceId("id-servizio-2");
+ ref2.setIban("iban-2");
+ List servicesRef = new ArrayList<>();
+ servicesRef.add(ref1);
+ servicesRef.add(ref2);
+
+ ci.setEnrollments(servicesRef);
+
+ ciRepository.deleteAll();
+ ciRepository.save(ci);
+ serviceRepository.deleteAll();
+ serviceRepository.save(s1);
+ serviceRepository.save(s2);
+ serviceRepository.save(s3);
+ serviceRepository.save(s4);
+ }
+
+ @AfterAll
+ void teardown() {
+ CosmosAsyncClient client = new CosmosClientBuilder().gatewayMode().endpointDiscoveryEnabled(false)
+ .endpoint(emulator.getEmulatorEndpoint()).key(emulator.getEmulatorKey()).buildAsyncClient();
+ client.getDatabase("db").delete();
+ emulator.stop();
+ }
+
+
+ @Test
+ void getECEnrollments() {
+ assertTrue(emulator.isRunning());
+ Organization org = enrollmentsService.getECEnrollments("organizationTest");
+ assertEquals("organizationTest", org.getFiscalCode());
+ assertEquals("Comune di Roma", org.getCompanyName());
+ }
+
+ @Test
+ void getECEnrollments_404() {
+ assertTrue(emulator.isRunning());
+ try {
+ // get a non-existent organization -> must raise a 404 exception
+ enrollmentsService.getECEnrollments("organizationFake");
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ void getSingleEnrollment() {
+ assertTrue(emulator.isRunning());
+ ServiceRef enrollment = enrollmentsService.getSingleEnrollment("organizationTest", "id-servizio-1");
+ assertEquals("id-servizio-1", enrollment.getServiceId());
+ assertEquals(null, enrollment.getOfficeName());
+ assertEquals("iban-1", enrollment.getIban());
+ }
+
+ @Test
+ void getSingleEnrollment_404() {
+ assertTrue(emulator.isRunning());
+ try {
+ // get a non-existent organization -> must raise a 404 exception
+ enrollmentsService.getSingleEnrollment("organizationFake", "id-servizio-1");
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+
+ try {
+ // get a non-existent enrollment -> must raise a 404 exception
+ enrollmentsService.getSingleEnrollment("organizationTest", "id-servizio-fake");
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ void createEC() {
+ assertTrue(emulator.isRunning());
+ Organization ci = new Organization();
+ ci.setFiscalCode("organizationNew");
+ ci.setCompanyName("Comune di Milano");
+ ci.setStatus(Status.ENABLED);
+ ServiceRef ref1 = new ServiceRef();
+ ref1.setServiceId("id-servizio-1");
+ ref1.setIban("iban-1");
+ List servicesRef = new ArrayList<>();
+ servicesRef.add(ref1);
+ ci.setEnrollments(servicesRef);
+ Organization orgCreated = enrollmentsService.createEC(ci);
+ assertEquals("organizationNew", orgCreated.getFiscalCode());
+ assertEquals("Comune di Milano", orgCreated.getCompanyName());
+ assertEquals(1, orgCreated.getEnrollments().size());
+ }
+
+ @Test
+ void createEC_404() {
+ assertTrue(emulator.isRunning());
+ // creation of an organization with enroll to a service that does not exist
+ Organization ci = new Organization();
+ ci.setFiscalCode("organizationNoService");
+ ci.setCompanyName("Comune di Milano");
+ ci.setStatus(Status.ENABLED);
+ ServiceRef ref1 = new ServiceRef();
+ ref1.setServiceId("id-servizio-fake");
+ ref1.setIban("iban-1");
+ List servicesRef = new ArrayList<>();
+ servicesRef.add(ref1);
+ ci.setEnrollments(servicesRef);
+
+ try {
+ // must raise a 404 exception
+ enrollmentsService.createEC(ci);
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ void createEC_409() {
+ assertTrue(emulator.isRunning());
+ // creation of an organization already present in the system
+ Organization ci = new Organization();
+ ci.setFiscalCode("organizationTest");
+ ci.setCompanyName("Comune di Milano");
+ ci.setStatus(Status.ENABLED);
+ ServiceRef ref1 = new ServiceRef();
+ ref1.setServiceId("id-servizio-1");
+ ref1.setIban("iban-1");
+ List servicesRef = new ArrayList<>();
+ servicesRef.add(ref1);
+ ci.setEnrollments(servicesRef);
+ try {
+ // must raise a 409 exception
+ enrollmentsService.createEC(ci);
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.CONFLICT, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ void createECEnrollment() {
+ assertTrue(emulator.isRunning());
+ EnrollmentModel enrollment =
+ EnrollmentModel.builder().iban("iban-3").officeName("Ufficio Tributario").build();
+ Organization org = enrollmentsService.createECEnrollment("organizationTest", "id-servizio-3", enrollment);
+ assertEquals("organizationTest", org.getFiscalCode());
+ assertEquals("Comune di Roma", org.getCompanyName());
+ // added an enrollment -> the size became 3
+ assertEquals(3, org.getEnrollments().size());
+ }
+
+ @Test
+ void createECEnrollment_404() {
+ assertTrue(emulator.isRunning());
+ EnrollmentModel enrollment =
+ EnrollmentModel.builder().iban("iban-3").officeName("Ufficio Tributario").build();
+
+ try {
+ // non-existent organization -> must raise a 404 exception
+ enrollmentsService.createECEnrollment("organizationFake", "id-servizio-1", enrollment);
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+
+ try {
+ // non-existent service -> must raise a 404 exception
+ enrollmentsService.createECEnrollment("organizationTest", "id-servizio-fake", enrollment);
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ void createECEnrollment_409() {
+ assertTrue(emulator.isRunning());
+ EnrollmentModel enrollment =
+ EnrollmentModel.builder().iban("iban-3").officeName("Ufficio Tributario").build();
+
+ try {
+ // enrollment to service already exist -> must raise a 409 exception
+ enrollmentsService.createECEnrollment("organizationTest", "id-servizio-1", enrollment);
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.CONFLICT, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+
+
+ }
+
+ @Test
+ void updateECEnrollment() {
+ assertTrue(emulator.isRunning());
+ EnrollmentModel enrollment =
+ EnrollmentModel.builder().iban("iban-updated-2").officeName("Ufficio Tributario Updated").build();
+ Organization org = enrollmentsService.updateECEnrollment("organizationTest", "id-servizio-2", enrollment);
+ assertEquals("organizationTest", org.getFiscalCode());
+ assertEquals("Comune di Roma", org.getCompanyName());
+ ServiceRef updatedEnrollment = org.getEnrollments().stream().filter(s -> s.getServiceId().equals("id-servizio-2")).findFirst().get();
+ assertEquals("iban-updated-2", updatedEnrollment.getIban());
+ assertEquals("Ufficio Tributario Updated", updatedEnrollment.getOfficeName());
+ }
+
+ @Test
+ void updateECEnrollment_404() {
+ assertTrue(emulator.isRunning());
+ EnrollmentModel enrollment =
+ EnrollmentModel.builder().iban("iban-updated-2").officeName("Ufficio Tributario Updated").build();
+ try {
+ // non-existent organization -> must raise a 404 exception
+ enrollmentsService.updateECEnrollment("organizationFake", "id-servizio-2", enrollment);
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+
+ try {
+ // non-existent service -> must raise a 404 exception
+ enrollmentsService.updateECEnrollment("organizationTest", "id-servizio-fake", enrollment);
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ void updateEC() {
+ assertTrue(emulator.isRunning());
+ OrganizationModel orgModel = OrganizationModel.builder().companyName("Comune di Roma").status(Status.DISABLED).build();
+ Organization org = enrollmentsService.updateEC("organizationTest", orgModel);
+ assertEquals("organizationTest", org.getFiscalCode());
+ assertEquals("Comune di Roma", org.getCompanyName());
+ assertEquals(Status.DISABLED, org.getStatus());
+ }
+
+ @Test
+ void updateEC_404() {
+ assertTrue(emulator.isRunning());
+ OrganizationModel orgModel = OrganizationModel.builder().companyName("Comune di Roma").status(Status.DISABLED).build();
+ try {
+ // non-existent organization -> must raise a 404 exception
+ enrollmentsService.updateEC("organizationFake", orgModel);
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+ }
+
+ @Test
+ void deleteECEnrollment() {
+ assertTrue(emulator.isRunning());
+ // Add a dummy enrollment
+ EnrollmentModel enrollment =
+ EnrollmentModel.builder().iban("iban-4").officeName("Ufficio Tributario 4").build();
+ Organization org = enrollmentsService.createECEnrollment("organizationTest", "id-servizio-4", enrollment);
+ assertEquals("organizationTest", org.getFiscalCode());
+ assertEquals("Comune di Roma", org.getCompanyName());
+ ServiceRef addedEnrollment = org.getEnrollments().stream().filter(s -> s.getServiceId().equals("id-servizio-4")).findFirst().get();
+ assertEquals("iban-4", addedEnrollment.getIban());
+ assertEquals("Ufficio Tributario 4", addedEnrollment.getOfficeName());
+
+ // Remove the dummy enrollment
+ enrollmentsService.deleteECEnrollment("organizationTest", "id-servizio-4");
+ // This line means the call was successful
+ assertTrue(true);
+ }
+
+ @Test
+ void deleteECEnrollment_404() {
+ assertTrue(emulator.isRunning());
+ try {
+ // non-existent organization -> must raise a 404 exception
+ enrollmentsService.deleteECEnrollment("organizationFake", "id-servizio-4");
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+
+ try {
+ // non-existent enrollment -> must raise a 404 exception
+ enrollmentsService.deleteECEnrollment("organizationTest", "id-servizio-fake");
+ fail();
+ } catch (AppException e) {
+ assertEquals(HttpStatus.NOT_FOUND, e.getHttpStatus());
+ } catch (Exception e) {
+ fail();
+ }
+
+ }
+
+}