diff --git a/apps/pom.xml b/apps/pom.xml
index 1feb3e17..ed8cc65c 100644
--- a/apps/pom.xml
+++ b/apps/pom.xml
@@ -16,17 +16,17 @@
it.pagopa.selfcare
onboarding-sdk-azure-storage
- 0.1.4
+ 0.1.6
it.pagopa.selfcare
onboarding-sdk-common
- 0.1.4
+ 0.1.6
it.pagopa.selfcare
onboarding-sdk-product
- 0.1.4
+ 0.1.6
diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java
index b940e2e1..2a18c1bd 100644
--- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java
+++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/controller/UserController.java
@@ -54,5 +54,23 @@ public Uni getUserInfo(@PathParam(value = "id") String userId,
return userService.retrievePerson(userId, productId, institutionId)
.map(user -> userMapper.toUserResponse(user, institutionId));
}
+
+ /**
+ * The deleteProducts function is used to delete logically the association institution and product.
+ *
+ * @param userId String
+ * @param institutionId String
+ * @param productId String
+ *
+ * @return A uni<void>
+ */
+ @Operation(summary = "Delete logically the association institution and product")
+ @DELETE
+ @Path(value = "/{userId}/institutions/{institutionId}/products/{productId}")
+ public Uni deleteProducts(@PathParam(value = "userId") String userId,
+ @PathParam(value = "institutionId") String institutionId,
+ @PathParam(value = "productId") String productId) {
+ return userService.deleteUserInstitutionProduct(userId, institutionId, productId);
+ }
}
diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java
index fc3a1f83..3598429f 100644
--- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java
+++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionService.java
@@ -23,4 +23,6 @@ public interface UserInstitutionService {
Multi findAllWithFilter(Map queryParameter);
Uni retrieveFirstFilteredUserInstitution(Map queryParameter);
+
+ Uni deleteUserInstitutionProduct(String userId, String institutionId, String productId);
}
diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java
index 9a4d6856..42adbeec 100644
--- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java
+++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserInstitutionServiceDefault.java
@@ -7,8 +7,11 @@
import it.pagopa.selfcare.user.controller.response.UserInstitutionResponse;
import it.pagopa.selfcare.user.entity.OnboardedProduct;
import it.pagopa.selfcare.user.entity.UserInstitution;
+import it.pagopa.selfcare.user.entity.filter.OnboardedProductFilter;
+import it.pagopa.selfcare.user.entity.filter.UserInstitutionFilter;
import it.pagopa.selfcare.user.mapper.UserInstitutionMapper;
import it.pagopa.selfcare.user.util.QueryUtils;
+import it.pagopa.selfcare.user.util.UserUtils;
import jakarta.enterprise.context.ApplicationScoped;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -33,6 +36,7 @@ public class UserInstitutionServiceDefault implements UserInstitutionService {
private final UserInstitutionMapper userInstitutionMapper;
private final QueryUtils queryUtils;
+ private final UserUtils userUtils;
@Override
public Uni findById(String id) {
@@ -64,6 +68,14 @@ public Uni retrieveFirstFilteredUserInstitution(Map deleteUserInstitutionProduct(String userId, String institutionId, String productId) {
+ OnboardedProductFilter onboardedProductFilter = OnboardedProductFilter.builder().productId(productId).build();
+ UserInstitutionFilter userInstitutionFilter = UserInstitutionFilter.builder().userId(userId).institutionId(institutionId).build();
+ Map filterMap = userUtils.retrieveMapForFilter(onboardedProductFilter.constructMap(), userInstitutionFilter.constructMap());
+ return updateUserStatusDao(filterMap, OnboardedProductState.DELETED);
+ }
+
@Override
public Multi findAllWithFilter(Map queryParameter) {
Document query = queryUtils.buildQueryDocument(queryParameter, USER_INSTITUTION_COLLECTION);
diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java
index 09c20e01..73eb4e2f 100644
--- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java
+++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserService.java
@@ -22,4 +22,6 @@ Multi findAllUserInstitutions(String institutionId,
List states,
List products,
List productRoles);
+
+ Uni deleteUserInstitutionProduct(String userId, String institutionId, String productId);
}
diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java
index dc7d1f5a..cda61ec6 100644
--- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java
+++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/service/UserServiceImpl.java
@@ -2,6 +2,7 @@
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
+import it.pagopa.selfcare.user.constant.OnboardedProductState;
import it.pagopa.selfcare.user.controller.response.UserInstitutionResponse;
import it.pagopa.selfcare.user.controller.response.UserProductResponse;
import it.pagopa.selfcare.user.entity.UserInstitution;
@@ -25,6 +26,7 @@
import java.util.*;
import static it.pagopa.selfcare.user.constant.CustomError.USER_NOT_FOUND_ERROR;
+import static it.pagopa.selfcare.user.constant.CustomError.USER_TO_UPDATE_NOT_FOUND;
import static it.pagopa.selfcare.user.util.GeneralUtils.formatQueryParameterList;
@RequiredArgsConstructor
@@ -97,6 +99,17 @@ public Multi findAllUserInstitutions(String institution
return userInstitutions.onItem().transform(userInstitutionMapper::toResponse);
}
+ @Override
+ public Uni deleteUserInstitutionProduct(String userId, String institutionId, String productId) {
+ return userInstitutionService.deleteUserInstitutionProduct(userId, institutionId, productId)
+ .onItem().transformToUni(aLong -> {
+ if (aLong < 1) {
+ return Uni.createFrom().failure(new ResourceNotFoundException(USER_TO_UPDATE_NOT_FOUND.getMessage()));
+ }
+ return Uni.createFrom().nullItem();
+ });
+ }
+
private Map buildQueryParams(String userId, String productId, String institutionId) {
OnboardedProductFilter onboardedProductFilter = OnboardedProductFilter.builder()
.productId(productId)
diff --git a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/util/UserUtils.java b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/util/UserUtils.java
index a7c35519..93b22c68 100644
--- a/apps/user-ms/src/main/java/it/pagopa/selfcare/user/util/UserUtils.java
+++ b/apps/user-ms/src/main/java/it/pagopa/selfcare/user/util/UserUtils.java
@@ -4,10 +4,19 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
@ApplicationScoped
@RequiredArgsConstructor
@Slf4j
public class UserUtils {
-
+ @SafeVarargs
+ public final Map retrieveMapForFilter(Map... maps) {
+ Map map = new HashMap<>();
+ Arrays.stream(maps).forEach(map::putAll);
+ return map;
+ }
}
\ No newline at end of file
diff --git a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInstitutionServiceTest.java b/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInstitutionServiceTest.java
index 3c628b0f..53b0a13e 100644
--- a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInstitutionServiceTest.java
+++ b/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserInstitutionServiceTest.java
@@ -134,6 +134,20 @@ void findAllWithFilter() {
assertEquals(1, actual.size());
}
+ @Test
+ void deleteUserInstitutionProduct(){
+ final String userId = "userId";
+ String institutionId = "institutionId";
+ PanacheMock.mock(UserInstitution.class);
+ ReactivePanacheUpdate update = Mockito.mock(ReactivePanacheUpdate.class);
+ when(UserInstitution.update(any(Document.class)))
+ .thenReturn(update);
+ when(update.where(any())).thenReturn(Uni.createFrom().item(1L));
+ UniAssertSubscriber subscriber = userInstitutionService.deleteUserInstitutionProduct(userId, institutionId, "productID")
+ .subscribe().withSubscriber(UniAssertSubscriber.create());
+ subscriber.assertCompleted().assertItem(1L);
+ }
+
private UserInstitution createDummyUserInstitution() {
UserInstitution userInstitution = new UserInstitution();
userInstitution.setId(ObjectId.get());
diff --git a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserServiceTest.java b/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserServiceTest.java
index f1acc234..b9f162d4 100644
--- a/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserServiceTest.java
+++ b/apps/user-ms/src/test/java/it.pagopa.selfcare.user/service/UserServiceTest.java
@@ -12,6 +12,7 @@
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.helpers.test.AssertSubscriber;
import io.smallrye.mutiny.helpers.test.UniAssertSubscriber;
+import io.smallrye.mutiny.subscription.UniSubscriber;
import it.pagopa.selfcare.user.controller.response.UserInstitutionResponse;
import it.pagopa.selfcare.user.controller.response.UserProductResponse;
import it.pagopa.selfcare.user.entity.OnboardedProduct;
@@ -35,9 +36,11 @@
import java.util.Map;
import java.util.UUID;
+import static it.pagopa.selfcare.user.constant.CustomError.USER_TO_UPDATE_NOT_FOUND;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
@QuarkusTest
@@ -177,4 +180,28 @@ void retrieveUsersTest() {
assertEquals(1, actual.size());
assertEquals(userInstitution.getUserId(), actual.get(0).getUserId());
}
+
+ @Test
+ void deleteUserInstitutionProductFound(){
+ when(userInstitutionService.deleteUserInstitutionProduct("userId", "institutionId", "productId")).thenReturn(Uni.createFrom().item(1L));
+ UniAssertSubscriber subscriber = userService
+ .deleteUserInstitutionProduct("userId", "institutionId", "productId")
+ .subscribe()
+ .withSubscriber(UniAssertSubscriber.create());
+
+ subscriber.assertCompleted();
+
+
+ }
+
+ @Test
+ void deleteUserInstitutionProductNotFound(){
+ when(userInstitutionService.deleteUserInstitutionProduct("userId", "institutionId", "productId")).thenReturn(Uni.createFrom().item(0L));
+ UniAssertSubscriber subscriber = userService
+ .deleteUserInstitutionProduct("userId", "institutionId", "productId")
+ .subscribe()
+ .withSubscriber(UniAssertSubscriber.create());
+
+ subscriber.assertFailedWith(ResourceNotFoundException.class, USER_TO_UPDATE_NOT_FOUND.getMessage());
+ }
}
diff --git a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java
index 595890de..cc148bbf 100644
--- a/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java
+++ b/apps/user-ms/src/test/java/it/pagopa/selfcare/user/controller/UserControllerTest.java
@@ -6,8 +6,10 @@
import io.quarkus.test.security.TestSecurity;
import io.restassured.http.ContentType;
import io.smallrye.mutiny.Uni;
+import it.pagopa.selfcare.user.exception.InvalidRequestException;
import it.pagopa.selfcare.user.exception.ResourceNotFoundException;
import it.pagopa.selfcare.user.service.UserService;
+import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.openapi.quarkus.user_registry_json.model.CertifiableFieldResourceOfLocalDate;
@@ -133,4 +135,62 @@ void testGetUserInfoFails() {
.statusCode(404);
}
+ /**
+ * Method under test:
+ * {@link UserController#deleteProducts(String, String, String)}
+ */
+ @Test
+ @TestSecurity(user = "userJwt")
+ void deleteDeleteProductsErrorTest() {
+ String PATH_USER_ID = "userId";
+ String PATH_INSTITUTION_ID = "institutionId";
+ String PATH_PRODUCT_ID = "productId";
+ String PATH_DELETE_PRODUCT = "{userId}/institutions/{institutionId}/products/{productId}";
+
+ var user = "user1";
+ var institution = "institution1";
+ var product = "product1";
+ Mockito.when(userService.deleteUserInstitutionProduct("user1","institution1", "product1"))
+ .thenThrow(InvalidRequestException.class);
+
+ given()
+ .when()
+ .pathParam(PATH_USER_ID, user)
+ .pathParam(PATH_INSTITUTION_ID, institution)
+ .pathParam(PATH_PRODUCT_ID, product)
+ .delete(PATH_DELETE_PRODUCT)
+ .then()
+ .statusCode(HttpStatus.SC_BAD_REQUEST);
+ }
+
+ /**
+ * Method under test:
+ * {@link UserController#deleteProducts(String, String, String)}
+ */
+ @Test
+ @TestSecurity(user = "userJwt")
+ void deleteDeleteProductsOKTest() {
+
+ String PATH_USER_ID = "userId";
+ String PATH_INSTITUTION_ID = "institutionId";
+ String PATH_PRODUCT_ID = "productId";
+ String PATH_DELETE_PRODUCT = "{userId}/institutions/{institutionId}/products/{productId}";
+
+ var user = "user123";
+ var institution = "institution123";
+ var product = "prod-pagopa";
+
+ Mockito.when(userService.deleteUserInstitutionProduct("user123", "institution123", "prod-pagopa"))
+ .thenReturn(Uni.createFrom().voidItem());
+
+ given()
+ .when()
+ .pathParam(PATH_USER_ID, user)
+ .pathParam(PATH_INSTITUTION_ID, institution)
+ .pathParam(PATH_PRODUCT_ID, product)
+ .delete(PATH_DELETE_PRODUCT)
+ .then()
+ .statusCode(HttpStatus.SC_NO_CONTENT);
+ }
+
}