From f48534e6457608fe6658b70ddbccc8c26ba98db8 Mon Sep 17 00:00:00 2001 From: Gaetano Miglionico Date: Fri, 7 Feb 2025 11:54:24 +0100 Subject: [PATCH] [SELC-6441] feat: getUserCount --- app/src/main/resources/swagger/api-docs.json | 135 ++++++++++++++++++ .../connector/api/UserApiConnector.java | 2 + .../connector/model/user/UserCount.java | 16 +++ .../rest/docs/openapi/selfcare-user-docs.json | 93 ++++++++++++ .../connector/rest/UserConnectorImpl.java | 9 ++ .../rest/model/mapper/UserMapper.java | 1 + .../connector/rest/UserConnectorImplTest.java | 34 +++++ .../dashboard/core/UserV2Service.java | 8 +- .../dashboard/core/UserV2ServiceImpl.java | 8 ++ .../dashboard/core/UserV2ServiceImplTest.java | 21 +++ .../controller/InstitutionV2Controller.java | 30 +++- .../web/model/mapper/UserMapperV2.java | 3 + .../web/model/user/UserCountResource.java | 26 ++++ .../resources/swagger/swagger_en.properties | 4 + .../resources/swagger/swagger_it.properties | 4 +- .../InstitutionV2ControllerTest.java | 41 +++++- 16 files changed, 423 insertions(+), 12 deletions(-) create mode 100644 connector-api/src/main/java/it/pagopa/selfcare/dashboard/connector/model/user/UserCount.java create mode 100644 web/src/main/java/it/pagopa/selfcare/dashboard/web/model/user/UserCountResource.java diff --git a/app/src/main/resources/swagger/api-docs.json b/app/src/main/resources/swagger/api-docs.json index 34921349b..1eb700c14 100644 --- a/app/src/main/resources/swagger/api-docs.json +++ b/app/src/main/resources/swagger/api-docs.json @@ -1113,6 +1113,108 @@ } ] } }, + "/v2/institutions/{institutionId}/products/{productId}/users/count" : { + "get" : { + "tags" : [ "institutions" ], + "summary" : "getUserCount", + "description" : "Service to get the number of users related to a specific pair of institution-product optionally filtered by role and status", + "operationId" : "v2GetUserCount", + "parameters" : [ { + "name" : "institutionId", + "in" : "path", + "description" : "Institution's unique internal identifier", + "required" : true, + "style" : "simple", + "schema" : { + "type" : "string" + } + }, { + "name" : "productId", + "in" : "path", + "description" : "Product's unique identifier", + "required" : true, + "style" : "simple", + "schema" : { + "type" : "string" + } + }, { + "name" : "roles", + "in" : "query", + "description" : "List of party roles (ex: roles=MANAGER,DELEGATE)", + "required" : false, + "style" : "form", + "explode" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "status", + "in" : "query", + "description" : "User's status list (ex: status=ACTIVE,SUSPENDED)", + "required" : false, + "style" : "form", + "explode" : true, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserCountResource" + } + } + } + }, + "400" : { + "description" : "Bad Request", + "content" : { + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "401" : { + "description" : "Unauthorized", + "content" : { + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "404" : { + "description" : "Not Found", + "content" : { + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "500" : { + "description" : "Internal Server Error", + "content" : { + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "security" : [ { + "bearerAuth" : [ "global" ] + } ] + } + }, "/v2/institutions/{institutionId}/products/{productId}/users/{userId}" : { "put" : { "tags" : [ "institutions" ], @@ -4321,6 +4423,39 @@ } } }, + "UserCountResource" : { + "title" : "UserCountResource", + "type" : "object", + "properties" : { + "count" : { + "type" : "integer", + "description" : "Number of users", + "format" : "int64" + }, + "institutionId" : { + "type" : "string", + "description" : "Institution's unique internal identifier" + }, + "productId" : { + "type" : "string", + "description" : "Product's unique identifier" + }, + "roles" : { + "type" : "array", + "description" : "Party role, available values: MANAGER, DELEGATE, SUB_DELEGATE, OPERATOR, ADMIN_EA", + "items" : { + "type" : "string" + } + }, + "status" : { + "type" : "array", + "description" : "User's status", + "items" : { + "type" : "string" + } + } + } + }, "UserGroupIdResource" : { "title" : "UserGroupIdResource", "required" : [ "id" ], diff --git a/connector-api/src/main/java/it/pagopa/selfcare/dashboard/connector/api/UserApiConnector.java b/connector-api/src/main/java/it/pagopa/selfcare/dashboard/connector/api/UserApiConnector.java index 94d32139e..094dadb90 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/dashboard/connector/api/UserApiConnector.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/dashboard/connector/api/UserApiConnector.java @@ -41,4 +41,6 @@ public interface UserApiConnector { UserInstitutionWithActionsDto getUserInstitutionWithActions(String userId, String institutionId, String productId); + UserCount getUserCount(String institutionId, String productId, List roles, List status); + } diff --git a/connector-api/src/main/java/it/pagopa/selfcare/dashboard/connector/model/user/UserCount.java b/connector-api/src/main/java/it/pagopa/selfcare/dashboard/connector/model/user/UserCount.java new file mode 100644 index 000000000..2a96d706b --- /dev/null +++ b/connector-api/src/main/java/it/pagopa/selfcare/dashboard/connector/model/user/UserCount.java @@ -0,0 +1,16 @@ +package it.pagopa.selfcare.dashboard.connector.model.user; + +import lombok.Data; + +import java.util.List; + +@Data +public class UserCount { + + private String institutionId; + private String productId; + private List roles; + private List status; + private Long count; + +} diff --git a/connector/rest/docs/openapi/selfcare-user-docs.json b/connector/rest/docs/openapi/selfcare-user-docs.json index 856f7041f..7ee8f0941 100644 --- a/connector/rest/docs/openapi/selfcare-user-docs.json +++ b/connector/rest/docs/openapi/selfcare-user-docs.json @@ -221,6 +221,68 @@ } ] } }, + "/institutions/{institutionId}/products/{productId}/users/count" : { + "get" : { + "tags" : [ "Institution" ], + "summary" : "Get the number of users for a certain product of an institution with a certain role and status", + "description" : "Count the number of users associated with a specific product of an institution, with an optional filter by roles and status. If no filter is specified count users with any role in status ACTIVE", + "operationId" : "getUsersCount", + "parameters" : [ { + "name" : "institutionId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "productId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "roles", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "status", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersCountResponse" + } + } + } + }, + "401" : { + "description" : "Not Authorized" + }, + "403" : { + "description" : "Not Allowed" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, "/institutions/{institutionId}/user-institutions" : { "get" : { "tags" : [ "Institution" ], @@ -1517,6 +1579,10 @@ } } }, + "PartyRole" : { + "enum" : [ "MANAGER", "DELEGATE", "SUB_DELEGATE", "OPERATOR", "ADMIN_EA" ], + "type" : "string" + }, "PermissionTypeEnum" : { "enum" : [ "ADMIN", "ANY" ], "type" : "string" @@ -1942,6 +2008,33 @@ } } }, + "UsersCountResponse" : { + "type" : "object", + "properties" : { + "institutionId" : { + "type" : "string" + }, + "productId" : { + "type" : "string" + }, + "roles" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/PartyRole" + } + }, + "status" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/OnboardedProductState" + } + }, + "count" : { + "format" : "int64", + "type" : "integer" + } + } + }, "UsersNotificationResponse" : { "type" : "object", "properties" : { diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/dashboard/connector/rest/UserConnectorImpl.java b/connector/rest/src/main/java/it/pagopa/selfcare/dashboard/connector/rest/UserConnectorImpl.java index 85684eb18..a52bea747 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/dashboard/connector/rest/UserConnectorImpl.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/dashboard/connector/rest/UserConnectorImpl.java @@ -67,6 +67,15 @@ public UserInstitutionWithActionsDto getUserInstitutionWithActions(String userId return userMapper.toUserInstitutionWithActionsDto(userInstitutionWithActions); } + @Override + @Retry(name = "retryTimeout") + public UserCount getUserCount(String institutionId, String productId, List roles, List status) { + log.trace("getUserCount start"); + UsersCountResponse usersCountResponse = userInstitutionApiRestClient._getUsersCount(institutionId, productId, roles, status) + .getBody(); + return userMapper.toUserCount(usersCountResponse); + } + @Override @Retry(name = "retryTimeout") public UserInstitution getProducts(String institutionId, String userId) { diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/dashboard/connector/rest/model/mapper/UserMapper.java b/connector/rest/src/main/java/it/pagopa/selfcare/dashboard/connector/rest/model/mapper/UserMapper.java index 4fce17f65..346d001d5 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/dashboard/connector/rest/model/mapper/UserMapper.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/dashboard/connector/rest/model/mapper/UserMapper.java @@ -45,6 +45,7 @@ default CertifiedField toCertifiedField(CertifiableFieldResponseString f @Mapping(target = "products", expression = "java(toProductInfoMap(userDashboardResponse.getProducts()))") UserInfo toUserInfo(UserDataResponse userDashboardResponse); + UserCount toUserCount(UsersCountResponse usersCountResponse); UserInstitutionWithActionsDto toUserInstitutionWithActionsDto(UserInstitutionWithActions userInstitutionWithActions); diff --git a/connector/rest/src/test/java/it/pagopa/selfcare/dashboard/connector/rest/UserConnectorImplTest.java b/connector/rest/src/test/java/it/pagopa/selfcare/dashboard/connector/rest/UserConnectorImplTest.java index 06ae9bbe3..c99b82681 100644 --- a/connector/rest/src/test/java/it/pagopa/selfcare/dashboard/connector/rest/UserConnectorImplTest.java +++ b/connector/rest/src/test/java/it/pagopa/selfcare/dashboard/connector/rest/UserConnectorImplTest.java @@ -801,4 +801,38 @@ void getUserByUserIdInstitutionIdAndProductAndStates_throwsResourceNotFoundExcep statusFilter); } + @Test + void getUserCount() { + final String institutionId = "institutionId"; + final String productId = "productId"; + final List roles = List.of("MANAGER", "DELEGATE"); + final List status = List.of("ACTIVE", "SUSPENDED"); + + final UsersCountResponse userCountResponse = new UsersCountResponse(); + userCountResponse.setInstitutionId(institutionId); + userCountResponse.setProductId(productId); + userCountResponse.setRoles(List.of( + it.pagopa.selfcare.user.generated.openapi.v1.dto.PartyRole.MANAGER, + it.pagopa.selfcare.user.generated.openapi.v1.dto.PartyRole.DELEGATE + )); + userCountResponse.setStatus(List.of( + OnboardedProductState.ACTIVE, + OnboardedProductState.SUSPENDED) + ); + userCountResponse.setCount(2L); + when(userInstitutionApiRestClient._getUsersCount(institutionId, productId, roles, status)) + .thenReturn(ResponseEntity.ok(userCountResponse)); + + final UserCount userCount = userConnector.getUserCount(institutionId, productId, roles, status); + assertEquals(institutionId, userCount.getInstitutionId()); + assertEquals(productId, userCount.getProductId()); + assertIterableEquals(roles, userCount.getRoles()); + assertIterableEquals(status, userCount.getStatus()); + assertEquals(2L, userCount.getCount()); + + verify(userInstitutionApiRestClient, times(1)) + ._getUsersCount(institutionId, productId, roles, status); + verifyNoMoreInteractions(userInstitutionApiRestClient); + } + } diff --git a/core/src/main/java/it/pagopa/selfcare/dashboard/core/UserV2Service.java b/core/src/main/java/it/pagopa/selfcare/dashboard/core/UserV2Service.java index 847fbdb24..e33e72382 100644 --- a/core/src/main/java/it/pagopa/selfcare/dashboard/core/UserV2Service.java +++ b/core/src/main/java/it/pagopa/selfcare/dashboard/core/UserV2Service.java @@ -1,10 +1,7 @@ package it.pagopa.selfcare.dashboard.core; import it.pagopa.selfcare.dashboard.connector.model.institution.InstitutionBase; -import it.pagopa.selfcare.dashboard.connector.model.user.UpdateUserRequestDto; -import it.pagopa.selfcare.dashboard.connector.model.user.User; -import it.pagopa.selfcare.dashboard.connector.model.user.UserInfo; -import it.pagopa.selfcare.dashboard.connector.model.user.UserToCreate; +import it.pagopa.selfcare.dashboard.connector.model.user.*; import java.util.Collection; import java.util.List; @@ -31,4 +28,7 @@ public interface UserV2Service { String createUsers(String institutionId, String productId, UserToCreate userToCreate); void addUserProductRoles(String institutionId, String productId, String userId, Set productRoles, String role); + + UserCount getUserCount(String institutionId, String productId, List roles, List status); + } diff --git a/core/src/main/java/it/pagopa/selfcare/dashboard/core/UserV2ServiceImpl.java b/core/src/main/java/it/pagopa/selfcare/dashboard/core/UserV2ServiceImpl.java index 86d12c16e..e265f4881 100644 --- a/core/src/main/java/it/pagopa/selfcare/dashboard/core/UserV2ServiceImpl.java +++ b/core/src/main/java/it/pagopa/selfcare/dashboard/core/UserV2ServiceImpl.java @@ -159,6 +159,14 @@ public void addUserProductRoles(String institutionId, String productId, String u log.trace("createOrUpdateUserByUserId end"); } + @Override + public UserCount getUserCount(String institutionId, String productId, List roles, List status) { + log.trace("getUserCount start"); + UserCount userCount = userApiConnector.getUserCount(institutionId, productId, roles, status); + log.trace("getUserCount end"); + return userCount; + } + private Institution verifyOnboardingStatus(String institutionId, String productId) { Institution institution = msCoreConnector.getInstitution(institutionId); if (institution.getOnboarding() == null || institution.getOnboarding().stream() diff --git a/core/src/test/java/it/pagopa/selfcare/dashboard/core/UserV2ServiceImplTest.java b/core/src/test/java/it/pagopa/selfcare/dashboard/core/UserV2ServiceImplTest.java index 2a3c96da8..8533b3e00 100644 --- a/core/src/test/java/it/pagopa/selfcare/dashboard/core/UserV2ServiceImplTest.java +++ b/core/src/test/java/it/pagopa/selfcare/dashboard/core/UserV2ServiceImplTest.java @@ -651,6 +651,27 @@ void createUsersByFiscalCodeWithInvalidProductRoles() { "The product doesn't allow adding users directly with these role and productRoles"); } + @Test + void getUserCount() { + final String institutionId = "institutionId"; + final String productId = "productId"; + final List roles = List.of("role1", "role2"); + final List status = List.of("status1", "status2"); + + final UserCount userCount = new UserCount(); + userCount.setInstitutionId(institutionId); + userCount.setProductId(productId); + userCount.setRoles(roles); + userCount.setStatus(status); + userCount.setCount(2L); + when(userApiConnectorMock.getUserCount(institutionId, productId, roles, status)).thenReturn(userCount); + + assertEquals(userCount, userV2ServiceImpl.getUserCount(institutionId, productId, roles, status)); + verify(userApiConnectorMock, times(1)) + .getUserCount(institutionId, productId, roles, status); + verifyNoMoreInteractions(userApiConnectorMock); + } + private static Product getProduct() { Product product = new Product(); Map map = new EnumMap<>(PartyRole.class); diff --git a/web/src/main/java/it/pagopa/selfcare/dashboard/web/controller/InstitutionV2Controller.java b/web/src/main/java/it/pagopa/selfcare/dashboard/web/controller/InstitutionV2Controller.java index 26ad346cb..c6f5c33de 100644 --- a/web/src/main/java/it/pagopa/selfcare/dashboard/web/controller/InstitutionV2Controller.java +++ b/web/src/main/java/it/pagopa/selfcare/dashboard/web/controller/InstitutionV2Controller.java @@ -1,6 +1,5 @@ package it.pagopa.selfcare.dashboard.web.controller; -import com.azure.core.annotation.QueryParam; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -11,6 +10,7 @@ import it.pagopa.selfcare.dashboard.connector.model.delegation.Order; import it.pagopa.selfcare.dashboard.connector.model.institution.Institution; import it.pagopa.selfcare.dashboard.connector.model.institution.InstitutionBase; +import it.pagopa.selfcare.dashboard.connector.model.user.UserCount; import it.pagopa.selfcare.dashboard.connector.model.user.UserInfo; import it.pagopa.selfcare.dashboard.core.DelegationService; import it.pagopa.selfcare.dashboard.core.InstitutionV2Service; @@ -22,6 +22,7 @@ import it.pagopa.selfcare.dashboard.web.model.mapper.InstitutionResourceMapper; import it.pagopa.selfcare.dashboard.web.model.mapper.UserMapper; import it.pagopa.selfcare.dashboard.web.model.mapper.UserMapperV2; +import it.pagopa.selfcare.dashboard.web.model.user.UserCountResource; import it.pagopa.selfcare.dashboard.web.model.user.UserIdResource; import it.pagopa.selfcare.dashboard.web.model.user.UserProductRoles; import lombok.RequiredArgsConstructor; @@ -36,10 +37,7 @@ import javax.validation.Valid; import javax.validation.constraints.Min; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.UUID; +import java.util.*; @Slf4j @@ -96,6 +94,28 @@ public List getInstitutions(Authentication authenticati return result; } + @GetMapping(value = "/{institutionId}/products/{productId}/users/count", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + @ApiOperation(value = "", notes = "${swagger.dashboard.institutions.api.getUserCount}", nickname = "v2GetUserCount") + @PreAuthorize("hasPermission(new it.pagopa.selfcare.dashboard.web.security.FilterAuthorityDomain(#institutionId, null, null), 'Selc:ListProductUsers')") + public UserCountResource getUserCount(@ApiParam("${swagger.dashboard.institutions.model.id}") + @PathVariable("institutionId") + String institutionId, + @ApiParam("${swagger.dashboard.products.model.id}") + @PathVariable("productId") + String productId, + @ApiParam(value = "${swagger.dashboard.product-role-mappings.model.partyRoleList}") + @RequestParam(name = "roles", required = false) String[] roles, + @ApiParam(value = "${swagger.dashboard.user.model.statusList}") + @RequestParam(name = "status", required = false) String[] status) { + log.trace("getUserCount start"); + UserCount userCount = userService.getUserCount(institutionId, productId, Arrays.asList(roles), Arrays.asList(status)); + UserCountResource result = userMapperV2.toUserCountResource(userCount); + log.debug(LogUtils.CONFIDENTIAL_MARKER, "getUserCount result = {}", result); + log.trace("getUserCount end"); + return result; + } + @PostMapping(value = "/{institutionId}/products/{productId}/users", produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.CREATED) @ApiOperation(value = "", notes = "${swagger.dashboard.institutions.api.createInstitutionProductUser}", nickname = "v2PostCreateInstitutionProductUser") diff --git a/web/src/main/java/it/pagopa/selfcare/dashboard/web/model/mapper/UserMapperV2.java b/web/src/main/java/it/pagopa/selfcare/dashboard/web/model/mapper/UserMapperV2.java index 9933aa2dc..da1cb5133 100644 --- a/web/src/main/java/it/pagopa/selfcare/dashboard/web/model/mapper/UserMapperV2.java +++ b/web/src/main/java/it/pagopa/selfcare/dashboard/web/model/mapper/UserMapperV2.java @@ -3,6 +3,7 @@ import it.pagopa.selfcare.dashboard.connector.model.user.*; import it.pagopa.selfcare.dashboard.web.model.UpdateUserDto; import it.pagopa.selfcare.dashboard.web.model.user.CertifiedFieldResource; +import it.pagopa.selfcare.dashboard.web.model.user.UserCountResource; import it.pagopa.selfcare.dashboard.web.model.user.UserResource; import it.pagopa.selfcare.onboarding.common.PartyRole; import org.apache.commons.lang3.StringUtils; @@ -24,6 +25,8 @@ public interface UserMapperV2 { @Mapping(target = "mobilePhone", expression = "java(toCertifiedFieldResource(model.getMobilePhone()))") UserResource toUserResource(User model); + UserCountResource toUserCountResource(UserCount userCount); + UpdateUserRequestDto fromUpdateUser(UpdateUserDto userDto); @Named("toCertifiedFieldResource") diff --git a/web/src/main/java/it/pagopa/selfcare/dashboard/web/model/user/UserCountResource.java b/web/src/main/java/it/pagopa/selfcare/dashboard/web/model/user/UserCountResource.java new file mode 100644 index 000000000..02e08a1f9 --- /dev/null +++ b/web/src/main/java/it/pagopa/selfcare/dashboard/web/model/user/UserCountResource.java @@ -0,0 +1,26 @@ +package it.pagopa.selfcare.dashboard.web.model.user; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +public class UserCountResource { + + @ApiModelProperty(value = "${swagger.dashboard.institutions.model.id}") + private String institutionId; + + @ApiModelProperty(value = "${swagger.dashboard.products.model.id}") + private String productId; + + @ApiModelProperty(value = "${swagger.dashboard.product-role-mappings.model.partyRole}") + private List roles; + + @ApiModelProperty(value = "${swagger.dashboard.user.model.status}") + private List status; + + @ApiModelProperty(value = "${swagger.dashboard.products.model.users}") + private Long count; + +} diff --git a/web/src/main/resources/swagger/swagger_en.properties b/web/src/main/resources/swagger/swagger_en.properties index 76f8da25f..665c7bce6 100644 --- a/web/src/main/resources/swagger/swagger_en.properties +++ b/web/src/main/resources/swagger/swagger_en.properties @@ -10,6 +10,7 @@ swagger.dashboard.institutions.api.getInstitutionUser=Service to get the users w swagger.dashboard.institutions.api.getInstitutionUsers=Service to get all the users related to a specific institution swagger.dashboard.institutions.api.getInstitutionProducts=Service to get all the products related to a specific institution swagger.dashboard.institutions.api.getInstitutionProductUsers=Service to get all the users related to a specific pair of institution-product +swagger.dashboard.institutions.api.getUserCount=Service to get the number of users related to a specific pair of institution-product optionally filtered by role and status swagger.dashboard.institutions.api.createInstitutionProductUser=Service to Create a user related to a specific pair of institution-product swagger.dashboard.institutions.api.getInstitutionOnboardingPending=Returns an institution's onboarding record by its ID only if its status is PENDING or TOBEVALIDATED swagger.dashboard.institutions.api.addUserProductRoles=Service to add a new role/product to a specific user @@ -85,6 +86,8 @@ swagger.dashboard.products.model.activatedAt=Date the products was activated swagger.dashboard.products.model.active=flag indicating whether the institution has a valid contract related to the product swagger.dashboard.products.model.authorized=flag indicating whether the logged user has the authorization to manage the product swagger.dashboard.products.model.backOfficeEnvironmentConfigurations=Environment-specific configurations for back-office redirection with Token Exchange +swagger.dashboard.products.model.users=Number of users +swagger.dashboard.product-role-mappings.model.partyRoleList=List of party roles (ex: roles=MANAGER,DELEGATE) swagger.dashboard.product-role-mappings.model.partyRole=Party role, available values: MANAGER, DELEGATE, SUB_DELEGATE, OPERATOR, ADMIN_EA swagger.dashboard.product-role-mappings.model.selcRole=Self Care role swagger.dashboard.product-role-mappings.model.multiroleAllowed=Indicates if an User can have more than one product role @@ -114,6 +117,7 @@ swagger.dashboard.user.model.productRole=User's role in product swagger.dashboard.user.model.products=Authorized user products swagger.dashboard.user.model.product=Authorized user product swagger.dashboard.user.model.status=User's status +swagger.dashboard.user.model.statusList=User's status list (ex: status=ACTIVE,SUSPENDED) swagger.dashboard.user.model.fiscalCode=User's fiscal code swagger.dashboard.user.model.extras=User's extra details swagger.dashboard.user.api.search=Retrieve the user for a given fiscal code diff --git a/web/src/main/resources/swagger/swagger_it.properties b/web/src/main/resources/swagger/swagger_it.properties index e88e60139..b55b99e4b 100644 --- a/web/src/main/resources/swagger/swagger_it.properties +++ b/web/src/main/resources/swagger/swagger_it.properties @@ -21,6 +21,7 @@ swagger.dashboard.products.model.activationDateTime=Data in cui e' stata attivat swagger.dashboard.products.api.getProducts=Il servizio permette il recupero della lista di prodotti PagoPa swagger.dashboard.product.api.getProductBrokers=Il servizio consente il recupero della lista di intermediari dato l'identificativo del prodotto e il tipo di ente swagger.dashboard.products.model.institutionType=Tipologia di ente +swagger.dashboard.products.model.users=Numero di utenti swagger.dashboard.brokers.model.code=Codice del partner swagger.dashboard.brokers.model.description=Descrizione del partner swagger.dashboard.brokers.model.enabled=Abilitato @@ -29,4 +30,5 @@ swagger.dashboard.support.model.email=Email dell'utente swagger.dashboard.support.model.productId=Identificativo del prodotto swagger.dashboard.support.model.userId=Identificativo dell'utente swagger.dashboard.support.model.institutionId=Identificativo dell'ente -swagger.dashboard.token.api.billingToken=Il servizio consente di recuperare il token per la fatturazione \ No newline at end of file +swagger.dashboard.token.api.billingToken=Il servizio consente di recuperare il token per la fatturazione +swagger.dashboard.institutions.api.getUserCount=Il servizio permette di ottenere il numero di utenti per una certa coppia prodotto - istituzione opzionalmente filtrando per ruolo e stato \ No newline at end of file diff --git a/web/src/test/java/it/pagopa/selfcare/dashboard/web/controller/InstitutionV2ControllerTest.java b/web/src/test/java/it/pagopa/selfcare/dashboard/web/controller/InstitutionV2ControllerTest.java index bfb908bc7..9b4689e3c 100644 --- a/web/src/test/java/it/pagopa/selfcare/dashboard/web/controller/InstitutionV2ControllerTest.java +++ b/web/src/test/java/it/pagopa/selfcare/dashboard/web/controller/InstitutionV2ControllerTest.java @@ -5,6 +5,7 @@ import it.pagopa.selfcare.dashboard.connector.model.delegation.*; import it.pagopa.selfcare.dashboard.connector.model.institution.Institution; import it.pagopa.selfcare.dashboard.connector.model.institution.InstitutionBase; +import it.pagopa.selfcare.dashboard.connector.model.user.UserCount; import it.pagopa.selfcare.dashboard.connector.model.user.UserInfo; import it.pagopa.selfcare.dashboard.connector.model.user.UserToCreate; import it.pagopa.selfcare.dashboard.core.DelegationService; @@ -14,6 +15,7 @@ import it.pagopa.selfcare.dashboard.web.model.CreateUserDto; import it.pagopa.selfcare.dashboard.web.model.mapper.InstitutionResourceMapperImpl; import it.pagopa.selfcare.dashboard.web.model.mapper.UserMapperV2Impl; +import it.pagopa.selfcare.dashboard.web.model.user.UserCountResource; import it.pagopa.selfcare.dashboard.web.model.user.UserProductRoles; import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.BeforeEach; @@ -35,8 +37,7 @@ import static it.pagopa.selfcare.commons.utils.TestUtils.mockInstance; import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -471,6 +472,42 @@ void getInstitutionOnboarding200() throws Exception { } + @Test + void getUserCount() throws Exception { + final String institutionId = "institutionId"; + final String productId = "productId"; + final String[] roles = { "role1", "role2" }; + final String[] status = { "status1", "status2" }; + + final UserCount userCount = new UserCount(); + userCount.setInstitutionId(institutionId); + userCount.setProductId(productId); + userCount.setRoles(Arrays.asList(roles)); + userCount.setStatus(Arrays.asList(status)); + userCount.setCount(2L); + when(userServiceMock.getUserCount(institutionId, productId, Arrays.asList(roles), Arrays.asList(status))).thenReturn(userCount); + + final MvcResult result = mockMvc.perform(MockMvcRequestBuilders + .get(BASE_URL + "/{institutionId}/products/{productId}/users/count", institutionId, productId) + .queryParam("roles", roles) + .queryParam("status", status) + .contentType(APPLICATION_JSON_VALUE) + .accept(APPLICATION_JSON_VALUE)) + .andExpect(status().isOk()) + .andReturn(); + + UserCountResource resource = objectMapper.readValue( + result.getResponse().getContentAsString(), new TypeReference<>() {}); + assertEquals(userCount.getInstitutionId(), resource.getInstitutionId()); + assertEquals(userCount.getProductId(), resource.getProductId()); + assertIterableEquals(userCount.getRoles(), resource.getRoles()); + assertIterableEquals(userCount.getStatus(), resource.getStatus()); + assertEquals(userCount.getCount(), resource.getCount()); + + verify(userServiceMock, times(1)) + .getUserCount(institutionId, productId, Arrays.asList(roles), Arrays.asList(status)); + verifyNoMoreInteractions(userServiceMock); + } private DelegationWithInfo dummyDelegation() { DelegationWithInfo delegation = new DelegationWithInfo();