diff --git a/.github/workflows/pr_ms.yml b/.github/workflows/pr_ms.yml index ab46b8934..c3fdb64e2 100644 --- a/.github/workflows/pr_ms.yml +++ b/.github/workflows/pr_ms.yml @@ -8,21 +8,11 @@ on: - main - releases/** types: + - opened + - edited - synchronize - reopened - ready_for_review - paths: - - '.github/workflows/pr_ms.yml' - - '.github/workflows/release_ms.yml' - - '.github/workflows/release_ms_pnpg.yml' - - '!.devops/**' - - '!.identity/**' - - '!helm/**' - - '!**.md' - - '!**ignore' - - '!infra/**' - - '!.terraform-version' - - '!CODEOWNERS' jobs: diff --git a/.github/workflows/release_ms.yml b/.github/workflows/release_ms.yml index ce82763e5..83ad915b8 100644 --- a/.github/workflows/release_ms.yml +++ b/.github/workflows/release_ms.yml @@ -4,17 +4,15 @@ on: push: branches: - main - - releases/** + - releases/* paths: - - '!.devops/**' - - '!.github/**' - - '!.identity/**' - - '!helm/**' - - '!**.md' - - '!.**ignore' - - '!infra/repository/**' - - '!.terraform-version' - - '!CODEOWNERS' + - 'app/**' + - 'connector/**' + - 'connector-api/**' + - 'core/**' + - 'infra/**' + - 'web/**' + - 'pom.xml' workflow_dispatch: inputs: diff --git a/.github/workflows/release_ms_pnpg.yml b/.github/workflows/release_ms_pnpg.yml index 6b4ce32fd..43c1fff4c 100644 --- a/.github/workflows/release_ms_pnpg.yml +++ b/.github/workflows/release_ms_pnpg.yml @@ -4,17 +4,15 @@ on: push: branches: - main - - releases/** + - releases/* paths: - - '!.devops/**' - - '!.github/**' - - '!.identity/**' - - '!helm/**' - - '!**.md' - - '!.**ignore' - - '!infra/repository/**' - - '!.terraform-version' - - '!CODEOWNERS' + - 'app/**' + - 'connector/**' + - 'connector-api/**' + - 'core/**' + - 'infra/**' + - 'web/**' + - 'pom.xml' workflow_dispatch: inputs: diff --git a/Dockerfile.new b/Dockerfile.new index a412eb39a..8f8f2be17 100644 --- a/Dockerfile.new +++ b/Dockerfile.new @@ -1,4 +1,4 @@ -FROM maven:3-eclipse-temurin-17 AS builder +FROM maven:3-eclipse-temurin-17@sha256:0d328fa6843bb26b60cf44d69833f241ffe96218fb29fa19df7a6603863eaae7 AS builder COPY . . @@ -18,7 +18,7 @@ ARG REPO_PASSWORD RUN mvn --global-settings settings.xml -DrepositoryOnboarding=${REPO_ONBOARDING} -DrepoLogin=${REPO_USERNAME} -DrepoPwd=${REPO_PASSWORD} clean package -DskipTests=true -FROM openjdk:17-jdk AS runtime +FROM openjdk:17-jdk@sha256:528707081fdb9562eb819128a9f85ae7fe000e2fbaeaf9f87662e7b3f38cb7d8 AS runtime ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' diff --git a/app/src/main/resources/config/core-config.properties b/app/src/main/resources/config/core-config.properties index 908ae3352..2aa620369 100644 --- a/app/src/main/resources/config/core-config.properties +++ b/app/src/main/resources/config/core-config.properties @@ -4,7 +4,7 @@ mscore.logoPath = ${PAGOPA_LOGO_URL:resources/logo.png} mscore.infoCamereEnable = ${INFOCAMERE_ENABLE:false} mscore.sender-mail = ${MAIL_SENDER_ADDRESS:test@test.it} mscore.destination-mails = ${DESTINATION_MAILS:} - +mscore.enableSendDelegationMail=${SEND_DELEGATION_PEC:false} mscore.sendEmailToInstitution = ${ONBOARDING_SEND_EMAIL_TO_INSTITUTION:false} mscore.institutionAlternativeEmail = ${ONBOARDING_INSTITUTION_ALTERNATIVE_EMAIL} mscore.onboarding-expiring-date = ${ONBOARDING_EXPIRING_DATE:60} diff --git a/app/src/main/resources/swagger/api-docs.json b/app/src/main/resources/swagger/api-docs.json index 6b7bc77d0..d84b538d1 100644 --- a/app/src/main/resources/swagger/api-docs.json +++ b/app/src/main/resources/swagger/api-docs.json @@ -105,6 +105,16 @@ "type" : "string", "enum" : [ "FULL", "NORMAL" ] } + }, { + "name" : "order", + "in" : "query", + "description" : "Order to show response NONE, ASC, DESC", + "required" : false, + "style" : "form", + "schema" : { + "type" : "string", + "enum" : [ "ASC", "DESC", "NONE" ] + } }, { "name" : "page", "in" : "query", @@ -2945,6 +2955,97 @@ } ] } }, + "/onboarding/verify" : { + "head" : { + "tags" : [ "Onboarding" ], + "summary" : "verify if onboardedProduct is already onboarded for institution", + "description" : "verify if onboardedProduct is already onboarded for institution", + "operationId" : "verifyOnboardingInfoByFiltersUsingHEAD", + "parameters" : [ { + "name" : "productId", + "in" : "query", + "description" : "Product's unique identifier", + "required" : true, + "style" : "form", + "schema" : { + "type" : "string" + } + }, { + "name" : "externalId", + "in" : "query", + "description" : "Institution's unique external identifier", + "required" : false, + "style" : "form", + "schema" : { + "type" : "string" + } + }, { + "name" : "taxCode", + "in" : "query", + "description" : "Institution's tax code", + "required" : false, + "style" : "form", + "schema" : { + "type" : "string" + } + }, { + "name" : "origin", + "in" : "query", + "description" : "Institution's origin", + "required" : false, + "style" : "form", + "schema" : { + "type" : "string" + } + }, { + "name" : "originId", + "in" : "query", + "description" : "Institution's id in the relative origin open data", + "required" : false, + "style" : "form", + "schema" : { + "type" : "string" + } + }, { + "name" : "subunitCode", + "in" : "query", + "description" : "Institution's subunit code", + "required" : false, + "style" : "form", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "204" : { + "description" : "No Content" + }, + "400" : { + "description" : "Bad Request", + "content" : { + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "404" : { + "description" : "Not Found", + "content" : { + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "security" : [ { + "bearerAuth" : [ "global" ] + } ] + } + }, "/notification-event/contracts" : { "put" : { "tags" : [ "kafka" ], diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/DelegationConnector.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/DelegationConnector.java index 62b4378a2..8842ffa67 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/DelegationConnector.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/DelegationConnector.java @@ -2,6 +2,7 @@ import it.pagopa.selfcare.mscore.constant.DelegationState; import it.pagopa.selfcare.mscore.constant.GetDelegationsMode; +import it.pagopa.selfcare.mscore.constant.Order; import it.pagopa.selfcare.mscore.model.delegation.Delegation; import java.util.List; @@ -10,7 +11,7 @@ public interface DelegationConnector { Delegation save(Delegation delegation); boolean checkIfExists(Delegation delegation); - List find(String from, String to, String productId, String search, String taxCode, GetDelegationsMode mode, Integer page, Integer size); + List find(String from, String to, String productId, String search, String taxCode, GetDelegationsMode mode, Order order, Integer page, Integer size); Delegation findByIdAndModifyStatus(String delegationId, DelegationState status); boolean checkIfDelegationsAreActive(String institutionId); } diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/InstitutionConnector.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/InstitutionConnector.java index de967630f..b12ce6a19 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/InstitutionConnector.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/InstitutionConnector.java @@ -4,6 +4,7 @@ import it.pagopa.selfcare.mscore.constant.RelationshipState; import it.pagopa.selfcare.mscore.constant.SearchMode; import it.pagopa.selfcare.mscore.model.institution.*; +import it.pagopa.selfcare.mscore.model.onboarding.VerifyOnboardingFilters; import java.time.OffsetDateTime; import java.util.List; @@ -56,4 +57,6 @@ public interface InstitutionConnector { List findByTaxCodeAndSubunitCode(String taxCode, String subunitCode); List findByOriginAndOriginId(String origin, String originId); + + Boolean existsOnboardingByFilters(VerifyOnboardingFilters filters); } diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/PartyRegistryProxyConnector.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/PartyRegistryProxyConnector.java index 3414ccc5c..bf81a397a 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/PartyRegistryProxyConnector.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/PartyRegistryProxyConnector.java @@ -24,5 +24,5 @@ public interface PartyRegistryProxyConnector { SaResource getSAFromAnac(String taxId); - AsResource getASFromIvass(String taxId); + ASResource getASFromIvass(String ivassCode); } diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/UserApiConnector.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/UserApiConnector.java new file mode 100644 index 000000000..5cbbb7a14 --- /dev/null +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/api/UserApiConnector.java @@ -0,0 +1,10 @@ +package it.pagopa.selfcare.mscore.api; + + +import java.util.List; + +public interface UserApiConnector { + + List getUserEmails(String institutionId, String productId); + +} diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/config/CoreConfig.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/config/CoreConfig.java index a0fdb14dc..1410c5bc6 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/mscore/config/CoreConfig.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/config/CoreConfig.java @@ -22,6 +22,7 @@ public class CoreConfig { private boolean sendEmailToInstitution; private Integer onboardingExpiringDate; private boolean infoCamereEnable; + private boolean enableSendDelegationMail; private BlobStorage blobStorage; @Data diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/constant/CustomError.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/constant/CustomError.java index 8f5aa7d3f..a9ae91095 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/mscore/constant/CustomError.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/constant/CustomError.java @@ -12,10 +12,12 @@ public enum CustomError { MANAGER_NOT_FOUND_ERROR("0033", "No onboarded managers for at least one of the institutions %s and product %s"), ROLES_NOT_ADMITTED_ERROR("0034","Roles %s are not admitted for this operation"), INSTITUTION_NOT_ONBOARDED("0004", "Institution having externalId %s is not onboarded for product %s"), + INSTITUTION_NOT_ONBOARDED_BY_FILTERS("0004", "Has not been found an onboarded Institution with the provided filters"), INSTITUTION_NOT_FOUND("0036", "Cannot find Institution using institutionId %s and externalInstitutionId %s"), INSTITUTION_LEGAL_NOT_FOUND("0037", "Institution with externalInstitutionId %s is not related to user"), CREATE_INSTITUTION_CONFLICT("0038", "Institution having externalId %s already exists"), CREATE_INSTITUTION_IPA_CONFLICT("0038", "Institution having taxCode %s and subunitCode %s already exists"), + CREATE_INSTITUTION_ORIGIN_CONFLICT("0038", "Institution having origin %s and originId %s already exists"), CREATE_INSTITUTION_NOT_FOUND("0039", "Institution having externalId %s not exists in registry"), INSTITUTION_TAX_CODE_NOT_FOUND("0040", "Cannot find Institution using taxCode %s"), ONBOARDING_INVALID_UPDATES("0046", "Cannot perform data overrides on institution having external id %s"), @@ -23,6 +25,7 @@ public enum CustomError { PRODUCTS_NOT_FOUND_ERROR("0030", "Products not found for institution having internalId %s"), ONBOARDING_INFO_INSTITUTION_NOT_FOUND("0050", "No onboarding information found for %s"), ONBOARDING_INFO_ERROR("0051", "Error getting onboarding info"), + ONBOARDING_INFO_FILTERS_ERROR("0052", "Invalid filters parameters to retrieve onboarding info"), ONBOARDING_BILLING_ERROR("0000", "Billing vatNumber and recipientCode are required"), ONBOARDING_BILLING_VATNUMBER_ERROR("0000", "Billing vatNumber is required"), ONBOARDING_PENDING("0000", "There is already an onboarding request for product %s pending"), diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/constant/Order.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/constant/Order.java new file mode 100644 index 000000000..c02e8db95 --- /dev/null +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/constant/Order.java @@ -0,0 +1,9 @@ +package it.pagopa.selfcare.mscore.constant; + +public enum Order { + + NONE, + ASC, + DESC; + +} diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/AsResource.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/ASResource.java similarity index 93% rename from connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/AsResource.java rename to connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/ASResource.java index d1a0444c4..98d2568ea 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/AsResource.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/ASResource.java @@ -4,7 +4,7 @@ import lombok.Data; @Data -public class AsResource { +public class ASResource { private String id; private String originId; private String taxCode; diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/Institution.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/Institution.java index 8e27a6c14..84c6b6171 100644 --- a/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/Institution.java +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/institution/Institution.java @@ -25,6 +25,7 @@ public class Institution { private String address; private String zipCode; private String taxCode; + private String ivassCode; private String city; private String county; private String country; diff --git a/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/onboarding/VerifyOnboardingFilters.java b/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/onboarding/VerifyOnboardingFilters.java new file mode 100644 index 000000000..3f1ea9138 --- /dev/null +++ b/connector-api/src/main/java/it/pagopa/selfcare/mscore/model/onboarding/VerifyOnboardingFilters.java @@ -0,0 +1,45 @@ +package it.pagopa.selfcare.mscore.model.onboarding; + +import it.pagopa.selfcare.mscore.constant.CustomError; +import it.pagopa.selfcare.mscore.constant.RelationshipState; +import it.pagopa.selfcare.mscore.exception.InvalidRequestException; +import lombok.Data; +import org.springframework.util.StringUtils; + +import java.util.List; + +@Data +public class VerifyOnboardingFilters { + private String productId; + private String externalId; + private String taxCode; + private String origin; + private String originId; + private String subunitCode; + private List validRelationshipStates; + + public VerifyOnboardingFilters(String productId, String externalId, String taxCode, String origin, String originId, String subunitCode) { + this.productId = productId; + + /* + We don't set the values of all the attributes of the class, but try to value only a portion of them based on different + search patterns priority that we intend to convey. + And if the provided parameters do not fall within the identified cases for a search then return exception. + */ + if (StringUtils.hasText(externalId)) { + this.externalId = externalId; + } else if (StringUtils.hasText(taxCode)) { + this.taxCode = taxCode; + this.subunitCode = subunitCode; + this.origin = origin; + } else if(StringUtils.hasText(subunitCode)) { + this.subunitCode = subunitCode; + this.origin = origin; + } else if (StringUtils.hasText(origin) && StringUtils.hasText(originId)) { + this.origin = origin; + this.originId = originId; + } else { + throw new InvalidRequestException(CustomError.ONBOARDING_INFO_FILTERS_ERROR.getMessage(), CustomError.ONBOARDING_INFO_FILTERS_ERROR.getCode()); + } + } +} diff --git a/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/DelegationConnectorImpl.java b/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/DelegationConnectorImpl.java index ca6b3d238..29da7b8b6 100644 --- a/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/DelegationConnectorImpl.java +++ b/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/DelegationConnectorImpl.java @@ -7,11 +7,13 @@ import it.pagopa.selfcare.mscore.connector.dao.model.mapper.DelegationInstitutionMapper; import it.pagopa.selfcare.mscore.constant.DelegationState; import it.pagopa.selfcare.mscore.constant.GetDelegationsMode; +import it.pagopa.selfcare.mscore.constant.Order; import it.pagopa.selfcare.mscore.model.delegation.Delegation; import it.pagopa.selfcare.mscore.model.delegation.DelegationInstitution; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.FindAndModifyOptions; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.*; @@ -29,6 +31,8 @@ @Component public class DelegationConnectorImpl implements DelegationConnector { + public static final String INSTITUTIONS = "institutions"; + public static final String DELEGATIONS = "Delegations"; private final DelegationRepository repository; private final DelegationEntityMapper delegationMapper; private final DelegationInstitutionMapper delegationInstitutionMapper; @@ -63,11 +67,13 @@ public boolean checkIfExists(Delegation delegation) { } @Override - public List find(String from, String to, String productId, String search, String taxCode, GetDelegationsMode mode, Integer page, Integer size) { + public List find(String from, String to, String productId, String search, String taxCode, GetDelegationsMode mode, Order order, Integer page, Integer size) { List criterias = new ArrayList<>(); Criteria criteria = new Criteria(); Pageable pageable = PageRequest.of(page, size); + criterias.add(Criteria.where(DelegationEntity.Fields.status.name()).is(DelegationState.ACTIVE.name())); + if (Objects.nonNull(from)) { criterias.add(Criteria.where(DelegationEntity.Fields.from.name()).is(from)); } @@ -80,27 +86,35 @@ public List find(String from, String to, String productId, String se if (Objects.nonNull(search)) { criterias.add(Criteria.where(DelegationEntity.Fields.institutionFromName.name()).regex("(?i)" + Pattern.quote(search))); } + + Sort.Direction sortDirection = order.equals(Order.ASC) ? Sort.Direction.ASC : Sort.Direction.DESC; + if (GetDelegationsMode.FULL.equals(mode)) { - GraphLookupOperation.GraphLookupOperationBuilder lookup = Aggregation.graphLookup("Institution") - .startWith(Objects.nonNull(from) ? "to" : "from") - .connectFrom(Objects.nonNull(from) ? "to" : "from") - .connectTo("_id"); + GraphLookupOperation.GraphLookupOperationBuilder lookup = createInstitutionGraphLookupOperationBuilder(from); MatchOperation matchOperation = new MatchOperation(new Criteria().andOperator(criterias.toArray(new Criteria[criterias.size()]))); + long skipLimit = (long) page * size; SkipOperation skip = Aggregation.skip(skipLimit); - LimitOperation limit = Aggregation.limit(skipLimit + size); + LimitOperation limit = Aggregation.limit(size); Aggregation aggregation; + if (Objects.nonNull(taxCode)) { - Criteria taxCodeCriteria = Criteria.where("institutions." + InstitutionEntity.Fields.taxCode.name()).is(taxCode); - MatchOperation matchTaxCodeOperation = new MatchOperation(new Criteria().andOperator(taxCodeCriteria)); - aggregation = Aggregation.newAggregation(matchOperation, lookup.as("institutions"), matchTaxCodeOperation, skip, limit); - } else { - aggregation = Aggregation.newAggregation(matchOperation, lookup.as("institutions"), skip, limit); + MatchOperation matchTaxCodeOperation = getMatchTaxCodeOperation(taxCode); + aggregation = Aggregation.newAggregation(matchOperation, lookup.as(INSTITUTIONS), matchTaxCodeOperation, skip, limit); + } + else { + if (!order.equals(Order.NONE)) { + SortOperation sortOperation = new SortOperation(Sort.by(sortDirection, DelegationEntity.Fields.institutionFromName.name())); + aggregation = Aggregation.newAggregation(matchOperation, sortOperation, lookup.as(INSTITUTIONS), skip, limit); + } + else { + aggregation = Aggregation.newAggregation(matchOperation, lookup.as(INSTITUTIONS), skip, limit); + } } - List result = mongoTemplate.aggregate(aggregation, "Delegations", DelegationInstitution.class).getMappedResults(); + List result = mongoTemplate.aggregate(aggregation, DELEGATIONS, DelegationInstitution.class).getMappedResults(); return result.stream() .map(Objects.nonNull(from) ? delegationInstitutionMapper::convertToDelegationBroker : @@ -108,12 +122,29 @@ public List find(String from, String to, String productId, String se .collect(Collectors.toList()); } - return repository.find(Query.query(criteria.andOperator(criterias)), pageable, DelegationEntity.class) + Query query = Query.query(criteria.andOperator(criterias)); + if (!order.equals(Order.NONE)) { + query = query.with(Sort.by(sortDirection, DelegationEntity.Fields.institutionFromName.name())); + } + + return repository.find(query, pageable, DelegationEntity.class) .stream() .map(delegationMapper::convertToDelegation) .collect(Collectors.toList()); } + private static GraphLookupOperation.GraphLookupOperationBuilder createInstitutionGraphLookupOperationBuilder(String from) { + return Aggregation.graphLookup(INSTITUTIONS) + .startWith(Objects.nonNull(from) ? "to" : "from") + .connectFrom(Objects.nonNull(from) ? "to" : "from") + .connectTo("_id"); + } + + private static MatchOperation getMatchTaxCodeOperation(String taxCode) { + Criteria taxCodeCriteria = Criteria.where("institutions." + InstitutionEntity.Fields.taxCode.name()).is(taxCode); + return new MatchOperation(new Criteria().andOperator(taxCodeCriteria)); + } + @Override public Delegation findByIdAndModifyStatus(String delegationId, DelegationState status) { Query query = Query.query(Criteria.where(DelegationEntity.Fields.id.name()).is(delegationId)); diff --git a/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/InstitutionConnectorImpl.java b/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/InstitutionConnectorImpl.java index 0980e7933..97e2766c3 100644 --- a/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/InstitutionConnectorImpl.java +++ b/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/InstitutionConnectorImpl.java @@ -12,6 +12,7 @@ import it.pagopa.selfcare.mscore.exception.InvalidRequestException; import it.pagopa.selfcare.mscore.exception.ResourceNotFoundException; import it.pagopa.selfcare.mscore.model.institution.*; +import it.pagopa.selfcare.mscore.model.onboarding.VerifyOnboardingFilters; import it.pagopa.selfcare.mscore.model.product.ProductStatus; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -47,7 +48,7 @@ public InstitutionConnectorImpl(InstitutionRepository repository, InstitutionEnt } @Override - public List findAll(){ + public List findAll() { return repository.findAll().stream().map(institutionMapper::convertToInstitution).collect(Collectors.toList()); } @@ -160,7 +161,7 @@ public Institution findByExternalIdAndProductId(String externalId, String produc @Override public List findOnboardingByIdAndProductId(String institutionId, String productId) { - Optional optionalInstitution = Objects.nonNull(productId) + Optional optionalInstitution = Objects.nonNull(productId) ? Optional .ofNullable(repository.findByInstitutionIdAndOnboardingProductId(institutionId, productId)) : repository.findById(institutionId); @@ -180,7 +181,7 @@ public List findInstitutionsByProductId(String productId, Integer p Objects.nonNull(size) ? size : 100); Page institutionEntities = repository.find(query, pageable, InstitutionEntity.class); - return institutionEntities.getContent().stream() + return institutionEntities.getContent().stream() .map(institutionMapper::convertToInstitution) .collect(Collectors.toList()); } @@ -273,7 +274,7 @@ public List findBrokers(String productId, InstitutionType type) { .and(Onboarding.Fields.status.name()).is(ProductStatus.ACTIVE))); List institutionEntities = repository.find(query, InstitutionEntity.class); - return institutionEntities.stream() + return institutionEntities.stream() .map(institutionMapper::convertToInstitution) .collect(Collectors.toList()); } @@ -300,6 +301,25 @@ public List findByOriginAndOriginId(String origin, String originId) .collect(Collectors.toList()); } + @Override + public Boolean existsOnboardingByFilters(VerifyOnboardingFilters filters) { + Criteria criteriaInstitution = CriteriaBuilder.builder() + .isIfNotNull(InstitutionEntity.Fields.externalId.name(), filters.getExternalId()) + .isIfNotNull(InstitutionEntity.Fields.taxCode.name(), filters.getTaxCode()) + .isIfNotNull(InstitutionEntity.Fields.origin.name(), filters.getOrigin()) + .isIfNotNull(InstitutionEntity.Fields.originId.name(), filters.getOriginId()) + .isIfNotNull(InstitutionEntity.Fields.subunitCode.name(), filters.getSubunitCode()) + .build(); + + Criteria criteriaOnboarding = Criteria.where(Onboarding.Fields.status.name()).in(filters.getValidRelationshipStates()) + .and(Onboarding.Fields.productId.name()).is(filters.getProductId()); + + return repository.exists(Query.query(criteriaInstitution) + .addCriteria(Criteria.where(InstitutionEntity.Fields.onboarding.name()) + .elemMatch(criteriaOnboarding)) + , InstitutionEntity.class); + } + private Query constructQueryWithSearchMode(List geo, SearchMode searchMode) { String geoQuery = InstitutionEntity.Fields.geographicTaxonomies.name() + "." + GeoTaxonomyEntity.Fields.code.name(); diff --git a/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/UserConnectorImpl.java b/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/UserConnectorImpl.java index 8a6b15f52..f52f551b3 100644 --- a/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/UserConnectorImpl.java +++ b/connector/dao/src/main/java/it/pagopa/selfcare/mscore/connector/dao/UserConnectorImpl.java @@ -356,7 +356,12 @@ public List getUserInfo(String userId, String instit } MatchOperation matchInstitutionExist = Aggregation.match(Criteria.where("institutions").size(1)); - MatchOperation matchOperation = new MatchOperation(new Criteria().andOperator(criterias.toArray(new Criteria[criterias.size()]))); + MatchOperation matchOperation; + if(!criterias.isEmpty()) { + matchOperation = new MatchOperation(new Criteria().andOperator(criterias.toArray(new Criteria[criterias.size()]))); + } else { + matchOperation = new MatchOperation(new Criteria()); + } Aggregation aggregation = Aggregation.newAggregation(matchUserId, unwindBindings, lookup, matchInstitutionExist, unwindProducts, matchOperation); return mongoOperations.aggregate(aggregation, "User", UserInstitutionAggregation.class).getMappedResults(); diff --git a/connector/dao/src/test/java/it/pagopa/selfcare/mscore/connector/dao/DelegationConnectorImplTest.java b/connector/dao/src/test/java/it/pagopa/selfcare/mscore/connector/dao/DelegationConnectorImplTest.java index f301fe3ca..37bc9054c 100644 --- a/connector/dao/src/test/java/it/pagopa/selfcare/mscore/connector/dao/DelegationConnectorImplTest.java +++ b/connector/dao/src/test/java/it/pagopa/selfcare/mscore/connector/dao/DelegationConnectorImplTest.java @@ -9,6 +9,7 @@ import it.pagopa.selfcare.mscore.constant.DelegationState; import it.pagopa.selfcare.mscore.constant.DelegationType; import it.pagopa.selfcare.mscore.constant.GetDelegationsMode; +import it.pagopa.selfcare.mscore.constant.Order; import it.pagopa.selfcare.mscore.exception.MsCoreException; import it.pagopa.selfcare.mscore.model.delegation.Delegation; import it.pagopa.selfcare.mscore.model.delegation.DelegationInstitution; @@ -130,7 +131,7 @@ void find_shouldGetData() { .find(any(), any(), any()); List response = delegationConnectorImpl.find(delegationEntity.getFrom(), - delegationEntity.getTo(), delegationEntity.getProductId(), null, null, GetDelegationsMode.NORMAL, PAGE_SIZE, MAX_PAGE_SIZE); + delegationEntity.getTo(), delegationEntity.getProductId(), null, null, GetDelegationsMode.NORMAL, Order.NONE, PAGE_SIZE, MAX_PAGE_SIZE); //Then assertNotNull(response); @@ -158,7 +159,7 @@ void getBrokersFullMode() { thenReturn(results); List response = delegationConnectorImpl.find(dummyDelegationEntity.getFrom(), null, - dummyDelegationEntity.getProductId(), null, null, GetDelegationsMode.FULL, PAGE_SIZE, MAX_PAGE_SIZE); + dummyDelegationEntity.getProductId(), null, null, GetDelegationsMode.FULL, Order.NONE, PAGE_SIZE, MAX_PAGE_SIZE); //Then assertNotNull(response); @@ -188,7 +189,7 @@ void getInstitutionsFullMode() { thenReturn(results); List response = delegationConnectorImpl.find(null, dummyDelegationEntity.getTo(), - dummyDelegationEntity.getProductId(), null, null, GetDelegationsMode.FULL, PAGE_SIZE, MAX_PAGE_SIZE); + dummyDelegationEntity.getProductId(), null, null, GetDelegationsMode.FULL, Order.ASC, PAGE_SIZE, MAX_PAGE_SIZE); //Then assertNotNull(response); @@ -247,7 +248,7 @@ void find_shouldGetDataPaginated() { thenReturn(results); List response = delegationConnectorImpl.find(null, - TO1, "productId", null, null, GetDelegationsMode.FULL, 0, 1); + TO1, "productId", null, null, GetDelegationsMode.FULL, Order.NONE, 0, 1); //Then assertNotNull(response); diff --git a/connector/dao/src/test/java/it/pagopa/selfcare/mscore/connector/dao/InstitutionConnectorImplTest.java b/connector/dao/src/test/java/it/pagopa/selfcare/mscore/connector/dao/InstitutionConnectorImplTest.java index 8d2f00749..0f14c679e 100644 --- a/connector/dao/src/test/java/it/pagopa/selfcare/mscore/connector/dao/InstitutionConnectorImplTest.java +++ b/connector/dao/src/test/java/it/pagopa/selfcare/mscore/connector/dao/InstitutionConnectorImplTest.java @@ -12,7 +12,9 @@ import it.pagopa.selfcare.mscore.exception.InvalidRequestException; import it.pagopa.selfcare.mscore.exception.ResourceNotFoundException; import it.pagopa.selfcare.mscore.model.institution.*; +import it.pagopa.selfcare.mscore.model.onboarding.VerifyOnboardingFilters; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.*; @@ -771,4 +773,35 @@ void findByOriginOriginId() { assertFalse(onboardings.isEmpty()); } + + @Test + @DisplayName("Should return true when onboarding exists by filters") + void shouldReturnTrueWhenOnboardingExistsByFilters() { + // Given + VerifyOnboardingFilters filters = new VerifyOnboardingFilters("productId", "externalId", "taxCode", "origin", "originId", "subunitCode"); + filters.setValidRelationshipStates(List.of(RelationshipState.ACTIVE)); + when(institutionRepository.exists(any(Query.class), any())).thenReturn(true); + + // When + Boolean exists = institutionConnectorImpl.existsOnboardingByFilters(filters); + + // Then + assertTrue(exists); + } + + @Test + @DisplayName("Should return false when onboarding does not exist by filters") + void shouldReturnFalseWhenOnboardingDoesNotExistByFilters() { + // Given + VerifyOnboardingFilters filters = new VerifyOnboardingFilters("productId", "externalId", "taxCode", "origin", "originId", "subunitCode"); + filters.setValidRelationshipStates(List.of(RelationshipState.ACTIVE)); + + when(institutionRepository.exists(any(Query.class), any())).thenReturn(false); + + // When + Boolean exists = institutionConnectorImpl.existsOnboardingByFilters(filters); + + // Then + assertFalse(exists); + } } \ No newline at end of file diff --git a/connector/rest/docs/openapi/registry_proxy.json b/connector/rest/docs/openapi/registry_proxy.json index fb8510db8..fa2a92c9c 100644 --- a/connector/rest/docs/openapi/registry_proxy.json +++ b/connector/rest/docs/openapi/registry_proxy.json @@ -910,6 +910,79 @@ } ] } }, + "/insurance-companies/origin/{originId}" : { + "get" : { + "tags" : [ "insurance-companies" ], + "summary" : "Search insurance company by its taxCode", + "description" : "Returns only one insurance company.", + "operationId" : "searchByOriginIdUsingGET", + "parameters" : [ { + "name" : "originId", + "in" : "path", + "description" : "insurance company's IVASS unique identifier", + "required" : true, + "style" : "simple", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/InsuranceCompanyResource" + } + } + } + }, + "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" ] + } ] + } + }, "/insurance-companies/{taxId}" : { "get" : { "tags" : [ "insurance-companies" ], diff --git a/connector/rest/docs/openapi/selfcare-user-docs.json b/connector/rest/docs/openapi/selfcare-user-docs.json new file mode 100644 index 000000000..0aceba1c4 --- /dev/null +++ b/connector/rest/docs/openapi/selfcare-user-docs.json @@ -0,0 +1,1492 @@ +{ + "openapi" : "3.0.3", + "info" : { + "title" : "user-ms API", + "version" : "1.0.0" + }, + "servers" : [ { + "url" : "http://localhost:8080", + "description" : "Auto generated value" + }, { + "url" : "http://0.0.0.0:8080", + "description" : "Auto generated value" + } ], + "paths" : { + "/authorize/{institutionId}" : { + "get" : { + "tags" : [ "User Permission Controller" ], + "summary" : "Get permission for a user in an institution", + "parameters" : [ { + "name" : "institutionId", + "in" : "path", + "required" : true, + "schema" : { + "minLength" : 1, + "type" : "string" + } + }, { + "name" : "permission", + "in" : "query", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/PermissionTypeEnum" + } + }, { + "name" : "productId", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "type" : "boolean" + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/institutions/{institutionId}/products/{productId}/createdAt" : { + "put" : { + "tags" : [ "Institution Controller" ], + "summary" : "The API updates user's onboarded product with createdAt passed in input", + "parameters" : [ { + "name" : "institutionId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "productId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "createdAt", + "in" : "query", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/LocalDateTime" + } + }, { + "name" : "userIds", + "in" : "query", + "required" : true, + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/institutions/{institutionId}/user-institutions" : { + "get" : { + "tags" : [ "Institution Controller" ], + "summary" : "The API retrieves users with optional filters in input as query params", + "parameters" : [ { + "name" : "institutionId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "productRoles", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "products", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "roles", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "states", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "userId", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserInstitutionResponse" + } + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/institutions/{institutionId}/users" : { + "get" : { + "tags" : [ "Institution Controller" ], + "summary" : "The API retrieves user's info including details of roles on products", + "parameters" : [ { + "name" : "institutionId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserProductResponse" + } + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users" : { + "get" : { + "tags" : [ "User Controller" ], + "summary" : "The API retrieves paged users with optional filters in input as query params", + "parameters" : [ { + "name" : "institutionId", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "page", + "in" : "query", + "schema" : { + "format" : "int32", + "default" : "0", + "type" : "integer" + } + }, { + "name" : "productRoles", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "products", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "roles", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/PartyRole" + } + } + }, { + "name" : "size", + "in" : "query", + "schema" : { + "format" : "int32", + "default" : "100", + "type" : "integer" + } + }, { + "name" : "states", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "userId", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserInstitutionResponse" + } + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + }, + "post" : { + "tags" : [ "User Controller" ], + "summary" : "The createOrUpdateByFiscalCode function is used to create a new user or update an existing one.", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateUserDto" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "type" : "string" + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/emails" : { + "get" : { + "tags" : [ "User Controller" ], + "summary" : "The API retrieves Users' emails using institution id and product id", + "parameters" : [ { + "name" : "institutionId", + "in" : "query", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "productId", + "in" : "query", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/ids" : { + "get" : { + "tags" : [ "User Controller" ], + "summary" : "Retrieve all users given their userIds", + "parameters" : [ { + "name" : "userIds", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserInstitutionResponse" + } + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/notification" : { + "get" : { + "tags" : [ "User Controller" ], + "summary" : "Retrieve all SC-User for DataLake filtered by optional productId", + "parameters" : [ { + "name" : "page", + "in" : "query", + "schema" : { + "format" : "int32", + "default" : "0", + "type" : "integer" + } + }, { + "name" : "productId", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "size", + "in" : "query", + "schema" : { + "format" : "int32", + "default" : "100", + "type" : "integer" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersNotificationResponse" + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/search" : { + "post" : { + "tags" : [ "User Controller" ], + "summary" : "Search user by fiscalCode", + "parameters" : [ { + "name" : "institutionId", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SearchUserDto" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDetailResponse" + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{id}" : { + "get" : { + "tags" : [ "User Controller" ], + "summary" : "Retrieves user given userId and optional ProductId", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "institutionId", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "productId", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserResponse" + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{id}/details" : { + "get" : { + "tags" : [ "User Controller" ], + "summary" : "Retrieves user's information from pdv: name, familyName, email, fiscalCode and workContacts", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "field", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "institutionId", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDetailResponse" + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{id}/institution/{institutionId}/product/{productId}/status" : { + "put" : { + "tags" : [ "User Controller" ], + "summary" : "Service to update user product status", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "institutionId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "productId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "status", + "in" : "query", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/OnboardedProductState" + } + } ], + "responses" : { + "204" : { + "description" : "No Content" + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{id}/status" : { + "put" : { + "tags" : [ "User Controller" ], + "summary" : "Update user status with optional filter for institution, product, role and productRole", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "institutionId", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "productId", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "productRole", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "role", + "in" : "query", + "schema" : { + "$ref" : "#/components/schemas/PartyRole" + } + }, { + "name" : "status", + "in" : "query", + "schema" : { + "$ref" : "#/components/schemas/OnboardedProductState" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{id}/user-registry" : { + "put" : { + "tags" : [ "User Controller" ], + "summary" : "Service to update user in user-registry and send notification when user data gets updated", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "institutionId", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UpdateUserRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{userId}" : { + "post" : { + "tags" : [ "User Controller" ], + "summary" : "The createOrUpdateByUserId function is used to update existing user adding userRole.", + "parameters" : [ { + "name" : "userId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AddUserRoleDto" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{userId}/institution/{institutionId}" : { + "get" : { + "tags" : [ "User Controller" ], + "summary" : "The retrieveUsers function is used to retrieve a list of users from the UserInstitution collection and userRegistry.\nAt first it try to retrieve a UserInstitution document associated with a logged user (admin)\nIf this userInstitution object is not null, so user has AdminRole, it try to retriew the userInstitutions filtered by given institutionId, roles, states, products and productRoles\nand optional given personId, otherwise it do the same query using the logged user id instead of personId.\nAfter that it retrieve personal user data, foreach userId retrieved, from userRegistry and return a stream of UserDataResponse objects containing the requested user data.", + "parameters" : [ { + "name" : "institutionId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "userId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "personId", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "productRoles", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "products", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "roles", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, { + "name" : "states", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserDataResponse" + } + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{userId}/institutions" : { + "get" : { + "tags" : [ "User Controller" ], + "summary" : "Retrieves products info and role which the user is enabled", + "parameters" : [ { + "name" : "userId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "institutionId", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "states", + "in" : "query", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserInfoResponse" + } + } + } + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, + "/users/{userId}/institutions/{institutionId}/products/{productId}" : { + "delete" : { + "tags" : [ "User Controller" ], + "summary" : "Delete logically the association institution and product", + "parameters" : [ { + "name" : "institutionId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "productId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "name" : "userId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "204" : { + "description" : "No Content" + }, + "403" : { + "description" : "Not Allowed" + }, + "401" : { + "description" : "Not Authorized" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + } + }, + "components" : { + "schemas" : { + "AddUserRoleDto" : { + "required" : [ "institutionId", "product" ], + "type" : "object", + "properties" : { + "institutionId" : { + "minLength" : 1, + "type" : "string" + }, + "product" : { + "$ref" : "#/components/schemas/Product" + }, + "institutionDescription" : { + "type" : "string" + }, + "institutionRootName" : { + "type" : "string" + }, + "userMailUuid" : { + "type" : "string" + }, + "hasToSendEmail" : { + "type" : "boolean" + } + } + }, + "CertifiableFieldResponseString" : { + "type" : "object", + "properties" : { + "value" : { + "type" : "string" + }, + "certified" : { + "$ref" : "#/components/schemas/CertificationEnum" + } + } + }, + "CertificationEnum" : { + "enum" : [ "NONE", "SPID" ], + "type" : "string" + }, + "CreateUserDto" : { + "required" : [ "institutionId", "user", "product" ], + "type" : "object", + "properties" : { + "institutionId" : { + "minLength" : 1, + "type" : "string" + }, + "user" : { + "$ref" : "#/components/schemas/User" + }, + "product" : { + "$ref" : "#/components/schemas/Product1" + }, + "institutionDescription" : { + "type" : "string" + }, + "institutionRootName" : { + "type" : "string" + }, + "hasToSendEmail" : { + "type" : "boolean" + } + } + }, + "Env" : { + "enum" : [ "ROOT", "DEV", "COLL", "PROD" ], + "type" : "string" + }, + "LocalDateTime" : { + "format" : "date-time", + "type" : "string", + "example" : "2022-03-10T12:15:50" + }, + "OnboardedProductResponse" : { + "type" : "object", + "properties" : { + "productId" : { + "type" : "string" + }, + "tokenId" : { + "type" : "string" + }, + "status" : { + "$ref" : "#/components/schemas/OnboardedProductState" + }, + "productRole" : { + "type" : "string" + }, + "role" : { + "$ref" : "#/components/schemas/PartyRole" + }, + "env" : { + "$ref" : "#/components/schemas/Env" + }, + "createdAt" : { + "$ref" : "#/components/schemas/LocalDateTime" + }, + "updatedAt" : { + "$ref" : "#/components/schemas/LocalDateTime" + } + } + }, + "OnboardedProductState" : { + "enum" : [ "ACTIVE", "PENDING", "TOBEVALIDATED", "SUSPENDED", "DELETED", "REJECTED" ], + "type" : "string" + }, + "PartyRole" : { + "enum" : [ "MANAGER", "DELEGATE", "SUB_DELEGATE", "OPERATOR" ], + "type" : "string" + }, + "PermissionTypeEnum" : { + "enum" : [ "ADMIN", "ANY" ], + "type" : "string" + }, + "Product" : { + "required" : [ "productId", "role" ], + "type" : "object", + "properties" : { + "productId" : { + "minLength" : 1, + "type" : "string" + }, + "role" : { + "$ref" : "#/components/schemas/PartyRole" + }, + "tokenId" : { + "type" : "string" + }, + "productRoles" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "Product1" : { + "required" : [ "productId", "role" ], + "type" : "object", + "properties" : { + "productId" : { + "minLength" : 1, + "type" : "string" + }, + "role" : { + "$ref" : "#/components/schemas/PartyRole" + }, + "tokenId" : { + "type" : "string" + }, + "productRoles" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "QueueEvent" : { + "enum" : [ "ADD", "UPDATE" ], + "type" : "string" + }, + "SearchUserDto" : { + "required" : [ "fiscalCode" ], + "type" : "object", + "properties" : { + "fiscalCode" : { + "type" : "string" + } + } + }, + "UpdateUserRequest" : { + "type" : "object", + "properties" : { + "name" : { + "type" : "string" + }, + "familyName" : { + "type" : "string" + }, + "email" : { + "type" : "string" + } + } + }, + "User" : { + "required" : [ "fiscalCode", "institutionEmail" ], + "type" : "object", + "properties" : { + "birthDate" : { + "type" : "string" + }, + "familyName" : { + "type" : "string" + }, + "name" : { + "type" : "string" + }, + "fiscalCode" : { + "minLength" : 1, + "type" : "string" + }, + "institutionEmail" : { + "minLength" : 1, + "type" : "string" + } + } + }, + "UserDataResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + }, + "institutionId" : { + "type" : "string" + }, + "institutionDescription" : { + "type" : "string" + }, + "institutionRootName" : { + "type" : "string" + }, + "userMailUuid" : { + "type" : "string" + }, + "role" : { + "type" : "string" + }, + "status" : { + "type" : "string" + }, + "products" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/OnboardedProductResponse" + } + }, + "userResponse" : { + "$ref" : "#/components/schemas/UserResponse" + } + } + }, + "UserDetailResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string" + }, + "fiscalCode" : { + "type" : "string" + }, + "name" : { + "$ref" : "#/components/schemas/CertifiableFieldResponseString" + }, + "familyName" : { + "$ref" : "#/components/schemas/CertifiableFieldResponseString" + }, + "email" : { + "$ref" : "#/components/schemas/CertifiableFieldResponseString" + }, + "workContacts" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/WorkContactResponse" + } + } + } + }, + "UserInfoResponse" : { + "type" : "object", + "properties" : { + "userId" : { + "type" : "string" + }, + "institutions" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserInstitutionRoleResponse" + } + } + } + }, + "UserInstitutionResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + }, + "institutionId" : { + "type" : "string" + }, + "institutionDescription" : { + "type" : "string" + }, + "institutionRootName" : { + "type" : "string" + }, + "userMailUuid" : { + "type" : "string" + }, + "products" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/OnboardedProductResponse" + } + } + } + }, + "UserInstitutionRoleResponse" : { + "type" : "object", + "properties" : { + "institutionId" : { + "type" : "string" + }, + "institutionName" : { + "type" : "string" + }, + "institutionRootName" : { + "type" : "string" + }, + "role" : { + "$ref" : "#/components/schemas/PartyRole" + }, + "status" : { + "$ref" : "#/components/schemas/OnboardedProductState" + } + } + }, + "UserNotificationResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string" + }, + "institutionId" : { + "type" : "string" + }, + "productId" : { + "type" : "string" + }, + "onboardingTokenId" : { + "type" : "string" + }, + "createdAt" : { + "$ref" : "#/components/schemas/LocalDateTime" + }, + "updatedAt" : { + "$ref" : "#/components/schemas/LocalDateTime" + }, + "eventType" : { + "$ref" : "#/components/schemas/QueueEvent" + }, + "user" : { + "$ref" : "#/components/schemas/UserToNotify" + } + } + }, + "UserProductResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string" + }, + "taxCode" : { + "type" : "string" + }, + "name" : { + "type" : "string" + }, + "surname" : { + "type" : "string" + }, + "email" : { + "type" : "string" + }, + "products" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/OnboardedProductResponse" + } + } + } + }, + "UserResponse" : { + "required" : [ "id", "name", "surname" ], + "type" : "object", + "properties" : { + "id" : { + "minLength" : 1, + "type" : "string" + }, + "taxCode" : { + "type" : "string" + }, + "name" : { + "pattern" : "\\S", + "type" : "string" + }, + "surname" : { + "pattern" : "\\S", + "type" : "string" + }, + "email" : { + "type" : "string" + }, + "workContacts" : { + "type" : "object", + "additionalProperties" : { + "type" : "string" + } + } + } + }, + "UserToNotify" : { + "type" : "object", + "properties" : { + "userId" : { + "type" : "string" + }, + "name" : { + "type" : "string" + }, + "familyName" : { + "type" : "string" + }, + "email" : { + "type" : "string" + }, + "role" : { + "$ref" : "#/components/schemas/PartyRole" + }, + "productRole" : { + "type" : "string" + }, + "relationshipStatus" : { + "$ref" : "#/components/schemas/OnboardedProductState" + } + } + }, + "UsersNotificationResponse" : { + "type" : "object", + "properties" : { + "users" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserNotificationResponse" + } + } + } + }, + "WorkContactResponse" : { + "type" : "object", + "properties" : { + "email" : { + "$ref" : "#/components/schemas/CertifiableFieldResponseString" + } + } + } + }, + "securitySchemes" : { + "SecurityScheme" : { + "type" : "http", + "description" : "Authentication", + "scheme" : "bearer", + "bearerFormat" : "JWT" + } + } + } +} \ No newline at end of file diff --git a/connector/rest/pom.xml b/connector/rest/pom.xml index 6fa59ced1..985c728a5 100644 --- a/connector/rest/pom.xml +++ b/connector/rest/pom.xml @@ -104,6 +104,44 @@ + + org.openapitools + openapi-generator-maven-plugin + 6.3.0 + + + user-ms + + generate + + process-resources + + ${project.basedir}/docs/openapi/selfcare-user-docs.json + spring + spring-cloud + + false + false + + true + ${project.groupId}.user.generated.openapi.v1 + ${project.groupId}.user.generated.openapi.v1.dto + ${project.groupId}.user.generated.openapi.v1.api + ${project.groupId}.user.generated.openapi.v1.config + @lombok.Builder; @lombok.NoArgsConstructor; @lombok.AllArgsConstructor + java8-localdatetime + true + true + none + source + false + false + true + + + + + diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/PartyRegistryProxyConnectorImpl.java b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/PartyRegistryProxyConnectorImpl.java index a1b7a4397..a0eb2abba 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/PartyRegistryProxyConnectorImpl.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/PartyRegistryProxyConnectorImpl.java @@ -180,16 +180,15 @@ public SaResource getSAFromAnac(String taxId) { } @Override - public AsResource getASFromIvass(String taxId) { + public ASResource getASFromIvass(String ivassCode) { try { - log.debug("getASFromIvass = {}", taxId); - Assert.hasText(taxId, "TaxId is required"); - ResponseEntity result = restClient._searchByTaxCodeUsingGET(taxId); - log.debug("getASFromIvass = {}", taxId); + if (ivassCode.matches("\\w*")) { log.debug("getASFromIvass = {}", ivassCode); } + Assert.hasText(ivassCode, "IvassCode is required"); + ResponseEntity result = restClient._searchByOriginIdUsingGET(ivassCode); if (result != null) { return asMapper.toResource(result.getBody()); } - throw new ResourceNotFoundException(String.format(CREATE_INSTITUTION_NOT_FOUND.getMessage(), taxId), CREATE_INSTITUTION_NOT_FOUND.getCode()); + throw new ResourceNotFoundException(String.format(CREATE_INSTITUTION_NOT_FOUND.getMessage(), ivassCode), CREATE_INSTITUTION_NOT_FOUND.getCode()); } catch (FeignException e) { throw new MsCoreException(e.getMessage(), String.valueOf(e.status())); } diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/UserApiConnectorImpl.java b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/UserApiConnectorImpl.java new file mode 100644 index 000000000..569edfeb1 --- /dev/null +++ b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/UserApiConnectorImpl.java @@ -0,0 +1,27 @@ +package it.pagopa.selfcare.mscore.connector.rest; + +import it.pagopa.selfcare.mscore.api.UserApiConnector; +import it.pagopa.selfcare.mscore.connector.rest.client.UserApiRestClient; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@Slf4j +public class UserApiConnectorImpl implements UserApiConnector { + + private final UserApiRestClient userApiRestClient; + + public UserApiConnectorImpl(UserApiRestClient userApiRestClient) { + this.userApiRestClient = userApiRestClient; + } + + @Override + public List getUserEmails(String institutionId, String productId){ + ResponseEntity> userEmails = userApiRestClient._usersEmailsGet(institutionId, productId); + return userEmails.getBody(); + } + +} diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/client/UserApiRestClient.java b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/client/UserApiRestClient.java new file mode 100644 index 000000000..8e2687444 --- /dev/null +++ b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/client/UserApiRestClient.java @@ -0,0 +1,8 @@ +package it.pagopa.selfcare.mscore.connector.rest.client; + +import it.pagopa.selfcare.user.generated.openapi.v1.api.UserControllerApi; +import org.springframework.cloud.openfeign.FeignClient; + +@FeignClient(name = "${rest-client.user-ms.serviceCode}", url = "${rest-client.user-ms.base-url}") +public interface UserApiRestClient extends UserControllerApi { +} diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/config/UserApiRestClientConfig.java b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/config/UserApiRestClientConfig.java new file mode 100644 index 000000000..c3aa77ce3 --- /dev/null +++ b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/config/UserApiRestClientConfig.java @@ -0,0 +1,15 @@ +package it.pagopa.selfcare.mscore.connector.rest.config; + +import it.pagopa.selfcare.commons.connector.rest.config.RestClientBaseConfig; +import it.pagopa.selfcare.mscore.connector.rest.client.UserApiRestClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@Import(RestClientBaseConfig.class) +@EnableFeignClients(clients = UserApiRestClient.class) +@PropertySource("classpath:config/user-rest-client.properties") +public class UserApiRestClientConfig { +} diff --git a/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/mapper/AsMapper.java b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/mapper/AsMapper.java index 8ec73ff63..3be6ac23d 100644 --- a/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/mapper/AsMapper.java +++ b/connector/rest/src/main/java/it/pagopa/selfcare/mscore/connector/rest/mapper/AsMapper.java @@ -1,6 +1,6 @@ package it.pagopa.selfcare.mscore.connector.rest.mapper; -import it.pagopa.selfcare.mscore.model.institution.AsResource; +import it.pagopa.selfcare.mscore.model.institution.ASResource; import it.pagopa.selfcare.registry_proxy.generated.openapi.v1.dto.InsuranceCompanyResource; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -8,5 +8,5 @@ @Mapper(componentModel = "spring") public interface AsMapper { @Mapping(target = "origin", source="origin.value") - AsResource toResource(InsuranceCompanyResource response); + ASResource toResource(InsuranceCompanyResource response); } diff --git a/connector/rest/src/main/resources/config/user-rest-client.properties b/connector/rest/src/main/resources/config/user-rest-client.properties new file mode 100644 index 000000000..6731874f0 --- /dev/null +++ b/connector/rest/src/main/resources/config/user-rest-client.properties @@ -0,0 +1,9 @@ +rest-client.user-ms.base-url=${SELFCARE_USER_URL:http://localhost:8080} +rest-client.user-ms.serviceCode=user-ms +rest-client.user-ms.institution.serviceCode=user-institution-ms +rest-client.user-permission.serviceCode=user-permission +feign.client.config.user-ms.requestInterceptors[0]=it.pagopa.selfcare.commons.connector.rest.interceptor.AuthorizationHeaderInterceptor +feign.client.config.user-ms.connectTimeout=${SELFCARE_USER_REST_CLIENT_CONNECT_TIMEOUT:${REST_CLIENT_CONNECT_TIMEOUT:5000}} +feign.client.config.user-ms.readTimeout=${SELFCARE_USER_REST_CLIENT_READ_TIMEOUT:${REST_CLIENT_READ_TIMEOUT:5000}} +feign.client.config.user-ms.loggerLevel=${SELFCARE_USER_REST_CLIENT_LOGGER_LEVEL:${REST_CLIENT_LOGGER_LEVEL:FULL}} +feign.client.config.user-ms.errorDecoder=it.pagopa.selfcare.mscore.connector.rest.decoder.FeignErrorDecoder \ No newline at end of file diff --git a/connector/rest/src/test/java/it/pagopa/selfcare/mscore/connector/rest/PartyRegistryProxyConnectorImplTest.java b/connector/rest/src/test/java/it/pagopa/selfcare/mscore/connector/rest/PartyRegistryProxyConnectorImplTest.java index bd1eb9af8..0c86b3bb4 100644 --- a/connector/rest/src/test/java/it/pagopa/selfcare/mscore/connector/rest/PartyRegistryProxyConnectorImplTest.java +++ b/connector/rest/src/test/java/it/pagopa/selfcare/mscore/connector/rest/PartyRegistryProxyConnectorImplTest.java @@ -236,7 +236,7 @@ void testGetCategory5() { FeignException feignException = mock(FeignException.class); when(partyRegistryProxyRestClient.getCategory(any(), any())) .thenThrow(feignException); - assertThrows(MsCoreException.class, () -> partyRegistryProxyConnectorImpl.getCategory("origin","code")); + assertThrows(MsCoreException.class, () -> partyRegistryProxyConnectorImpl.getCategory("origin", "code")); verify(partyRegistryProxyRestClient).getCategory(any(), any()); } @@ -530,7 +530,7 @@ void shouldGetSa() { } @Test - void getSAFromAnac(){ + void getSAFromAnac() { //given String taxId = "taxId"; when(partyRegistryProxyRestClient.getSaByTaxId(anyString())).thenReturn(pdndResponse); @@ -542,7 +542,7 @@ void getSAFromAnac(){ } @Test - void getSAFromAnacNotFound(){ + void getSAFromAnacNotFound() { //given String taxId = "taxId"; when(partyRegistryProxyRestClient.getSaByTaxId(anyString())).thenThrow(ResourceNotFoundException.class); @@ -554,29 +554,38 @@ void getSAFromAnacNotFound(){ } @Test - void getASFromIvass(){ + void getASFromIvass() { //given - ResponseEntity response = new ResponseEntity<>(asResponse, HttpStatus.FOUND); - String taxId = "taxId"; - when(partyRegistryProxyRestClient._searchByTaxCodeUsingGET(anyString())).thenReturn(response); + ResponseEntity response = new ResponseEntity<>(asResponse, HttpStatus.FOUND); + String ivassCode = "ivassCode"; + when(partyRegistryProxyRestClient._searchByOriginIdUsingGET(anyString())).thenReturn(response); //when - AsResource result = partyRegistryProxyConnectorImpl.getASFromIvass(taxId); + ASResource result = partyRegistryProxyConnectorImpl.getASFromIvass(ivassCode); //then checkNotNullFields(result); - verify(partyRegistryProxyRestClient, times(1))._searchByTaxCodeUsingGET(taxId); + verify(partyRegistryProxyRestClient, times(1))._searchByOriginIdUsingGET(ivassCode); } @Test - void getASFromIvassNotFound(){ + void getASFromIvassNotFound() { //given - String taxId = "taxId"; - when(partyRegistryProxyRestClient._searchByTaxCodeUsingGET(anyString())).thenThrow(ResourceNotFoundException.class); + String ivassCode = "ivassCode"; + when(partyRegistryProxyRestClient._searchByOriginIdUsingGET(anyString())).thenReturn(null); + //when - Executable executable = () -> partyRegistryProxyConnectorImpl.getASFromIvass(taxId); + Executable executable = () -> partyRegistryProxyConnectorImpl.getASFromIvass(ivassCode); //then assertThrows(ResourceNotFoundException.class, executable); - verify(partyRegistryProxyRestClient, times(1))._searchByTaxCodeUsingGET(taxId); + verify(partyRegistryProxyRestClient, times(1))._searchByOriginIdUsingGET(ivassCode); } + @Test + void shouldThrowResourceNotFoundExceptionWhenIvassCodeNotFound() { + String ivassCode = "12345"; + + when(partyRegistryProxyRestClient._searchByOriginIdUsingGET(ivassCode)).thenReturn(null); + + assertThrows(ResourceNotFoundException.class, () -> partyRegistryProxyConnectorImpl.getASFromIvass(ivassCode)); + } } diff --git a/connector/rest/src/test/java/it/pagopa/selfcare/mscore/connector/rest/UserApiConnectorImplTest.java b/connector/rest/src/test/java/it/pagopa/selfcare/mscore/connector/rest/UserApiConnectorImplTest.java new file mode 100644 index 000000000..b675d57ce --- /dev/null +++ b/connector/rest/src/test/java/it/pagopa/selfcare/mscore/connector/rest/UserApiConnectorImplTest.java @@ -0,0 +1,45 @@ +package it.pagopa.selfcare.mscore.connector.rest; + +import it.pagopa.selfcare.mscore.connector.rest.client.UserApiRestClient; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ContextConfiguration(classes = {UserApiConnectorImpl.class}) +@ExtendWith(SpringExtension.class) +class UserApiConnectorImplTest { + + @Autowired + private UserApiConnectorImpl userApiConnector; + + @MockBean + private UserApiRestClient userApiRestClient; + + @Test + void getUserEmailsByInstitutionAndProduct(){ + //given + final String institutionId = "institutionId"; + final String productId = "productId"; + ResponseEntity> emails = new ResponseEntity<>(List.of("email"), HttpStatus.OK); + + when(userApiRestClient._usersEmailsGet(anyString(), anyString())).thenReturn(emails); + + //when + List userEmails = userApiConnector.getUserEmails(institutionId, productId); + //then + assertFalse(userEmails.isEmpty()); + verify(userApiRestClient, times(1))._usersEmailsGet(institutionId, productId); + + } +} \ No newline at end of file diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/DelegationService.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/DelegationService.java index 835032b5c..9a13b4930 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/DelegationService.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/DelegationService.java @@ -1,6 +1,7 @@ package it.pagopa.selfcare.mscore.core; import it.pagopa.selfcare.mscore.constant.GetDelegationsMode; +import it.pagopa.selfcare.mscore.constant.Order; import it.pagopa.selfcare.mscore.model.delegation.Delegation; import java.util.List; @@ -10,7 +11,7 @@ public interface DelegationService { Delegation createDelegation(Delegation delegation); boolean checkIfExists(Delegation delegation); - List getDelegations(String from, String to, String productId, String search, String taxCode, GetDelegationsMode mode, Optional page, Optional size); + List getDelegations(String from, String to, String productId, String search, String taxCode, GetDelegationsMode mode, Optional order, Optional page, Optional size); Delegation createDelegationFromInstitutionsTaxCode(Delegation delegation); void deleteDelegationByDelegationId(String delegationId); } diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/DelegationServiceImpl.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/DelegationServiceImpl.java index 0909dae00..8f974421a 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/DelegationServiceImpl.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/DelegationServiceImpl.java @@ -5,6 +5,7 @@ import it.pagopa.selfcare.mscore.constant.CustomError; import it.pagopa.selfcare.mscore.constant.DelegationState; import it.pagopa.selfcare.mscore.constant.GetDelegationsMode; +import it.pagopa.selfcare.mscore.constant.Order; import it.pagopa.selfcare.mscore.exception.MsCoreException; import it.pagopa.selfcare.mscore.exception.ResourceConflictException; import it.pagopa.selfcare.mscore.exception.ResourceNotFoundException; @@ -163,8 +164,8 @@ public boolean checkIfExists(Delegation delegation) { @Override public List getDelegations(String from, String to, String productId, String search, String taxCode, GetDelegationsMode mode, - Optional page, Optional size) { + Optional order, Optional page, Optional size) { int pageSize = size.filter(s -> s > 0).filter(s -> s <= DEFAULT_DELEGATIONS_PAGE_SIZE).orElse(DEFAULT_DELEGATIONS_PAGE_SIZE); - return delegationConnector.find(from, to, productId, search, taxCode, mode, page.orElse(0), pageSize); + return delegationConnector.find(from, to, productId, search, taxCode, mode, order.orElse(Order.NONE), page.orElse(0), pageSize); } } diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/InstitutionServiceImpl.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/InstitutionServiceImpl.java index 3768c3843..9f5688ef1 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/InstitutionServiceImpl.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/InstitutionServiceImpl.java @@ -109,11 +109,11 @@ public void retrieveInstitutionsWithFilter(String externalId, String productId, @Override public List getInstitutions(String taxCode, String subunitCode, String origin, String originId) { - if(StringUtils.hasText(taxCode) && (StringUtils.hasText(origin) || StringUtils.hasText(originId))) { + if (StringUtils.hasText(taxCode) && (StringUtils.hasText(origin) || StringUtils.hasText(originId))) { throw new InvalidRequestException(GenericError.GET_INSTITUTIONS_REQUEST_ERROR.getMessage(), GenericError.GET_INSTITUTIONS_REQUEST_ERROR.getCode()); } - if(StringUtils.hasText(taxCode)) { + if (StringUtils.hasText(taxCode)) { return institutionConnector.findByTaxCodeAndSubunitCode(taxCode, subunitCode); } else { return institutionConnector.findByOriginAndOriginId(origin, originId); @@ -175,11 +175,7 @@ public Institution createInstitutionFromAnac(Institution institution) { public Institution createInstitutionFromIvass(Institution institution) { return createInstitutionStrategyFactory.createInstitutionStrategyIvass(institution) .createInstitution(CreateInstitutionStrategyInput.builder() - .taxCode(institution.getTaxCode()) - .subunitCode(institution.getSubunitCode()) - .subunitType(Optional.ofNullable(institution.getSubunitType()) - .map(InstitutionPaSubunitType::valueOf) - .orElse(null)) + .ivassCode(institution.getOriginId()) .build()); } @@ -191,6 +187,7 @@ public Institution createInstitutionFromInfocamere(Institution institution) { .description(institution.getDescription()) .build()); } + @Override public Institution createInstitutionByExternalId(String externalId) { checkIfAlreadyExists(externalId); @@ -311,7 +308,7 @@ public List retrieveInstitutionGeoTaxonomies(Institution i public Optional retrieveGeoTaxonomies(String code) { try { return Optional.of(partyRegistryProxyConnector.getExtByCode(code)); - } catch (ResourceNotFoundException e){ + } catch (ResourceNotFoundException e) { return Optional.empty(); } } diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/MailNotificationServiceImpl.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/MailNotificationServiceImpl.java index b27a2fada..60437e5e3 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/MailNotificationServiceImpl.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/MailNotificationServiceImpl.java @@ -14,7 +14,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; import java.util.List; import java.util.Map; @@ -33,8 +32,6 @@ public class MailNotificationServiceImpl implements MailNotificationService { private final EmailConnector emailConnector; private final MailParametersMapper mailParametersMapper; private final CoreConfig coreConfig; - private final UserConnector userConnector; - private final UserRegistryConnector userRegistryConnector; public void sendMailForDelegation(String institutionName, String productId, String partnerId) { try { @@ -47,15 +44,17 @@ public void sendMailForDelegation(String institutionName, String productId, Stri } mailParameters = mailParametersMapper.getDelegationNotificationParameter(institutionName, product.getTitle(), partnerInstitution.getDescription()); log.debug(MAIL_PARAMETER_LOG, mailParameters); - List userDestinationMail = getUsersEmailByInstitutionAndProduct(partnerInstitution.getId(), productId); + List userDestinationMail = getUsersEmailByInstitutionAndProductV2(partnerInstitution.getId(), productId); log.info(DESTINATION_MAIL_LOG, userDestinationMail); userNotificationService.sendDelegationUserNotification(userDestinationMail, mailParametersMapper.getDelegationUserNotificationPath(), product.getTitle(), mailParameters); log.info("create-delegation-user-email-notification :: Email successful sent"); - List institutionDestinationMail = getDestinationMails(partnerInstitution); - log.info(DESTINATION_MAIL_LOG, institutionDestinationMail); - emailConnector.sendMail(mailParametersMapper.getDelegationNotificationPath(), institutionDestinationMail, null, product.getTitle(), mailParameters, null); - log.info("create-delegation-institution-email-notification :: Email successful sent"); + if (coreConfig.isEnableSendDelegationMail()) { + List institutionDestinationMail = getDestinationMails(partnerInstitution); + log.info(DESTINATION_MAIL_LOG, institutionDestinationMail); + emailConnector.sendMail(mailParametersMapper.getDelegationNotificationPath(), institutionDestinationMail, null, product.getTitle(), mailParameters, null); + log.info("create-delegation-institution-email-notification :: Email successful sent"); + } } catch (Exception e) { log.error("create-delegation-email-notification :: Impossible to send email. Error: {}", e.getMessage(), e); } @@ -69,15 +68,8 @@ private List getDestinationMails(Institution institution) { } } - private List getUsersEmailByInstitutionAndProduct(String institutionId, String productId) { - return userConnector.findUsersByInstitutionIdAndProductId(institutionId, productId).stream() - .map(userId -> userRegistryConnector.getUserByInternalIdWithCustomFields(userId, "workContacts")) - .map(User::getWorkContacts) - .filter(Objects::nonNull) - .map(workContactMap -> workContactMap.get(institutionId)) - .filter(Objects::nonNull) - .map(WorkContact::getEmail) - .filter(StringUtils::hasText) - .toList(); + + private List getUsersEmailByInstitutionAndProductV2(String institutionId, String productId){ + return userApiConnector.getUserEmails(institutionId, productId); } } diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/OnboardingService.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/OnboardingService.java index bb6955bd1..de2ef623d 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/OnboardingService.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/OnboardingService.java @@ -3,10 +3,7 @@ import it.pagopa.selfcare.commons.base.security.PartyRole; import it.pagopa.selfcare.mscore.model.institution.Institution; import it.pagopa.selfcare.mscore.model.institution.Onboarding; -import it.pagopa.selfcare.mscore.model.onboarding.OnboardingInfo; -import it.pagopa.selfcare.mscore.model.onboarding.OnboardingOperatorsRequest; -import it.pagopa.selfcare.mscore.model.onboarding.OnboardingUsersRequest; -import it.pagopa.selfcare.mscore.model.onboarding.ResourceResponse; +import it.pagopa.selfcare.mscore.model.onboarding.*; import it.pagopa.selfcare.mscore.model.user.RelationshipInfo; import it.pagopa.selfcare.mscore.model.user.UserToOnboard; @@ -18,6 +15,8 @@ public interface OnboardingService { void verifyOnboardingInfoSubunit(String taxCode, String subunitCode, String productId); + void verifyOnboardingInfoByFilters(VerifyOnboardingFilters filters); + List getOnboardingInfo(String institutionId, String institutionExternalId, String[] states, String userId); Institution persistOnboarding(String institutionId, String productId, List users, Onboarding onboarding); @@ -28,4 +27,5 @@ public interface OnboardingService { ResourceResponse retrieveDocument(String relationshipId); + } diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/OnboardingServiceImpl.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/OnboardingServiceImpl.java index bc3260daa..77e86365b 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/OnboardingServiceImpl.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/OnboardingServiceImpl.java @@ -68,7 +68,19 @@ public void verifyOnboardingInfoSubunit(String taxCode, String subunitCode, Stri } @Override - public List getOnboardingInfo(String institutionId, String institutionExternalId, String[] states, String userId) { + public void verifyOnboardingInfoByFilters(VerifyOnboardingFilters filters) { + filters.setValidRelationshipStates(UtilEnumList.VALID_RELATIONSHIP_STATES); + + Boolean existsOnboardingValid = institutionConnector.existsOnboardingByFilters(filters); + if (Boolean.FALSE.equals(existsOnboardingValid)) { + throw new ResourceNotFoundException(CustomError.INSTITUTION_NOT_ONBOARDED_BY_FILTERS.getMessage(), + CustomError.INSTITUTION_NOT_ONBOARDED_BY_FILTERS.getCode()); + } + } + + @Override + public List getOnboardingInfo(String institutionId, String institutionExternalId, String[] + states, String userId) { List relationshipStateList = OnboardingInfoUtils.getRelationShipStateList(states); List onboardingInfoList = new ArrayList<>(); @@ -86,25 +98,26 @@ public List getOnboardingInfo(String institutionId, String insti } @Override - public Institution persistOnboarding(String institutionId, String productId,List users, Onboarding onboarding) { + public Institution persistOnboarding(String institutionId, String + productId, List users, Onboarding onboarding) { log.trace("persistForUpdate start"); log.debug("persistForUpdate institutionId = {}, productId = {}, users = {}", institutionId, productId, users); onboarding.setStatus(RelationshipState.ACTIVE); onboarding.setProductId(productId); - if(Objects.isNull(onboarding.getCreatedAt())) { + if (Objects.isNull(onboarding.getCreatedAt())) { onboarding.setCreatedAt(OffsetDateTime.now()); } //Verify if onboarding exists, in case onboarding must fail final Institution institution = institutionConnector.findById(institutionId); - if(Optional.ofNullable(institution.getOnboarding()).flatMap(onboardings -> onboardings.stream() + if (Optional.ofNullable(institution.getOnboarding()).flatMap(onboardings -> onboardings.stream() .filter(item -> item.getProductId().equals(productId) && UtilEnumList.VALID_RELATIONSHIP_STATES.contains(item.getStatus())) - .findAny()).isPresent()){ + .findAny()).isPresent()) { throw new InvalidRequestException(String.format(CustomError.PRODUCT_ALREADY_ONBOARDED.getMessage(), institution.getTaxCode(), productId), - CustomError.PRODUCT_ALREADY_ONBOARDED.getCode()); + CustomError.PRODUCT_ALREADY_ONBOARDED.getCode()); } try { @@ -153,7 +166,8 @@ private TokenUser toTokenUser(UserToOnboard user) { } @Override - public List onboardingUsers(OnboardingUsersRequest request, String loggedUserName, String loggedUserSurname) { + public List onboardingUsers(OnboardingUsersRequest request, String loggedUserName, String + loggedUserSurname) { Product product = Optional.ofNullable(productService.getProductIsValid(request.getProductId())) @@ -186,7 +200,7 @@ private void fillUserIdAndCreateIfNotExist(UserToOnboard user, String institutio userRegistry = userService.retrieveUserFromUserRegistryByFiscalCode(user.getTaxCode()); //We must save mail institution if it is not found on WorkContracts - if(Objects.nonNull(user.getEmail()) && + if (Objects.nonNull(user.getEmail()) && (Objects.isNull(userRegistry.getWorkContacts()) || !userRegistry.getWorkContacts().containsKey(institutionId))) { userRegistry = userService.persistWorksContractToUserRegistry(user.getTaxCode(), user.getEmail(), institutionId); } @@ -197,7 +211,8 @@ private void fillUserIdAndCreateIfNotExist(UserToOnboard user, String institutio } @Override - public List onboardingOperators(OnboardingOperatorsRequest onboardingOperatorRequest, PartyRole role, String loggedUserName, String loggedUserSurname) { + public List onboardingOperators(OnboardingOperatorsRequest + onboardingOperatorRequest, PartyRole role, String loggedUserName, String loggedUserSurname) { OnboardingInstitutionUtils.verifyUsers(onboardingOperatorRequest.getUsers(), List.of(role)); Institution institution = institutionService.retrieveInstitutionById(onboardingOperatorRequest.getInstitutionId()); @@ -230,7 +245,8 @@ public ResourceResponse retrieveDocument(String relationshipId) { } } - private List getUserInstitutionAggregation(String userId, String institutionId, String externalId, List relationshipStates) { + private List getUserInstitutionAggregation(String userId, String + institutionId, String externalId, List relationshipStates) { List states = relationshipStates.stream().map(Enum::name).collect(Collectors.toList()); UserInstitutionFilter filter = new UserInstitutionFilter(userId, institutionId, externalId, states); List userInstitutionAggregation = userService.findUserInstitutionAggregation(filter); diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyCommon.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyCommon.java index 002b8e37c..efbf858eb 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyCommon.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyCommon.java @@ -9,6 +9,8 @@ import java.util.List; +import static it.pagopa.selfcare.mscore.constant.CustomError.CREATE_INSTITUTION_ORIGIN_CONFLICT; + @Slf4j @Component public class CreateInstitutionStrategyCommon { @@ -19,11 +21,18 @@ public CreateInstitutionStrategyCommon(InstitutionConnector institutionConnector } protected void checkIfAlreadyExistsByTaxCodeAndSubunitCode(String taxCode, String subunitCode) { - List institutions = institutionConnector.findByTaxCodeAndSubunitCode(taxCode, subunitCode); if (!institutions.isEmpty()) throw new ResourceConflictException(String .format(CustomError.CREATE_INSTITUTION_IPA_CONFLICT.getMessage(), taxCode, subunitCode), CustomError.CREATE_INSTITUTION_CONFLICT.getCode()); } + + protected void checkIfAlreadyExistByOriginAndOriginId(String origin, String originId) { + List institutions = institutionConnector.findByOriginAndOriginId(origin, originId); + if (!institutions.isEmpty()) + throw new ResourceConflictException(String.format( + CREATE_INSTITUTION_ORIGIN_CONFLICT.getMessage(), origin, originId), + CREATE_INSTITUTION_ORIGIN_CONFLICT.getCode()); + } } diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyIvass.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyIvass.java index f91cca572..565d6da5b 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyIvass.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyIvass.java @@ -5,7 +5,7 @@ import it.pagopa.selfcare.mscore.constant.Origin; import it.pagopa.selfcare.mscore.core.strategy.input.CreateInstitutionStrategyInput; import it.pagopa.selfcare.mscore.exception.MsCoreException; -import it.pagopa.selfcare.mscore.model.institution.AsResource; +import it.pagopa.selfcare.mscore.model.institution.ASResource; import it.pagopa.selfcare.mscore.model.institution.Institution; import lombok.extern.slf4j.Slf4j; @@ -31,10 +31,9 @@ public void setInstitution(Institution institution) { @Override public Institution createInstitution(CreateInstitutionStrategyInput strategyInput) { + checkIfAlreadyExistByOriginAndOriginId(Origin.IVASS.name(), strategyInput.getIvassCode()); - checkIfAlreadyExistsByTaxCodeAndSubunitCode(strategyInput.getTaxCode(), strategyInput.getSubunitCode()); - - AsResource asResource = partyRegistryProxyConnector.getASFromIvass(strategyInput.getTaxCode()); + ASResource asResource = partyRegistryProxyConnector.getASFromIvass(strategyInput.getIvassCode()); institution = addFieldsToInstitution(asResource); try { @@ -44,9 +43,9 @@ public Institution createInstitution(CreateInstitutionStrategyInput strategyInpu } } - private Institution addFieldsToInstitution(AsResource asResource) { - - institution.setExternalId(institution.getTaxCode()); + private Institution addFieldsToInstitution(ASResource asResource) { + institution.setTaxCode(asResource.getTaxCode()); + institution.setExternalId(asResource.getOriginId()); institution.setOrigin(Origin.IVASS.getValue()); institution.setOriginId(asResource.getOriginId()); institution.setCreatedAt(OffsetDateTime.now()); diff --git a/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/input/CreateInstitutionStrategyInput.java b/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/input/CreateInstitutionStrategyInput.java index ab2473e39..22322025d 100644 --- a/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/input/CreateInstitutionStrategyInput.java +++ b/core/src/main/java/it/pagopa/selfcare/mscore/core/strategy/input/CreateInstitutionStrategyInput.java @@ -13,6 +13,7 @@ public class CreateInstitutionStrategyInput { private String taxCode; + private String ivassCode; private String description; private InstitutionPaSubunitType subunitType; private List geographicTaxonomies; diff --git a/core/src/test/java/it/pagopa/selfcare/mscore/core/DelegationServiceImplTest.java b/core/src/test/java/it/pagopa/selfcare/mscore/core/DelegationServiceImplTest.java index 9734eaf49..8a745ea8b 100644 --- a/core/src/test/java/it/pagopa/selfcare/mscore/core/DelegationServiceImplTest.java +++ b/core/src/test/java/it/pagopa/selfcare/mscore/core/DelegationServiceImplTest.java @@ -4,6 +4,7 @@ import it.pagopa.selfcare.mscore.api.DelegationConnector; import it.pagopa.selfcare.mscore.constant.DelegationState; import it.pagopa.selfcare.mscore.constant.GetDelegationsMode; +import it.pagopa.selfcare.mscore.constant.Order; import it.pagopa.selfcare.mscore.exception.MsCoreException; import it.pagopa.selfcare.mscore.exception.ResourceConflictException; import it.pagopa.selfcare.mscore.exception.ResourceNotFoundException; @@ -176,12 +177,12 @@ void find_shouldGetData() { //Given Delegation delegation = new Delegation(); delegation.setId("id"); - when(delegationConnector.find(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(List.of(delegation)); + when(delegationConnector.find(any(), any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(List.of(delegation)); //When List response = delegationServiceImpl.getDelegations("from", "to", "productId", null, null, - GetDelegationsMode.NORMAL, Optional.of(0), Optional.of(100)); + GetDelegationsMode.NORMAL, Optional.empty(), Optional.of(0), Optional.of(100)); //Then - verify(delegationConnector).find(any(), any(), any(), any(), any(), any(), any(), any()); + verify(delegationConnector).find(any(), any(), any(), any(), any(), any(), any(), any(), any()); assertNotNull(response); assertFalse(response.isEmpty()); @@ -196,12 +197,12 @@ void find_shouldGetData_fullMode() { //Given Delegation delegation = new Delegation(); delegation.setId("id"); - when(delegationConnector.find(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(List.of(delegation)); + when(delegationConnector.find(any(), any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(List.of(delegation)); //When List response = delegationServiceImpl.getDelegations("from", null, "productId", null, null, - GetDelegationsMode.FULL, Optional.of(0), Optional.of(0)); + GetDelegationsMode.FULL, Optional.of(Order.DESC), Optional.of(0), Optional.of(0)); //Then - verify(delegationConnector).find(any(), any(), any(), any(), any(), any(), any(), any()); + verify(delegationConnector).find(any(), any(), any(), any(), any(), any(), any(), any(), any()); assertNotNull(response); assertFalse(response.isEmpty()); @@ -216,12 +217,12 @@ void find_shouldGetData_fullMode_defaultPage() { //Given Delegation delegation = new Delegation(); delegation.setId("id"); - when(delegationConnector.find(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(List.of(delegation)); + when(delegationConnector.find(any(), any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(List.of(delegation)); //When List response = delegationServiceImpl.getDelegations("from", null, "productId", null, null, - GetDelegationsMode.FULL, Optional.empty(), Optional.empty()); + GetDelegationsMode.FULL, Optional.of(Order.DESC), Optional.empty(), Optional.empty()); //Then - verify(delegationConnector).find(any(), any(), any(), any(), any(), any(), any(), any()); + verify(delegationConnector).find(any(), any(), any(), any(), any(), any(), any(), any(), any()); assertNotNull(response); assertFalse(response.isEmpty()); diff --git a/core/src/test/java/it/pagopa/selfcare/mscore/core/MailNotificationServiceImplTest.java b/core/src/test/java/it/pagopa/selfcare/mscore/core/MailNotificationServiceImplTest.java index eeaada6c6..d8cbf4087 100644 --- a/core/src/test/java/it/pagopa/selfcare/mscore/core/MailNotificationServiceImplTest.java +++ b/core/src/test/java/it/pagopa/selfcare/mscore/core/MailNotificationServiceImplTest.java @@ -1,6 +1,9 @@ package it.pagopa.selfcare.mscore.core; -import it.pagopa.selfcare.mscore.api.*; +import it.pagopa.selfcare.mscore.api.EmailConnector; +import it.pagopa.selfcare.mscore.api.InstitutionConnector; +import it.pagopa.selfcare.mscore.api.ProductConnector; +import it.pagopa.selfcare.mscore.api.UserApiConnector; import it.pagopa.selfcare.mscore.config.CoreConfig; import it.pagopa.selfcare.mscore.config.MailTemplateConfig; import it.pagopa.selfcare.mscore.core.util.MailParametersMapper; @@ -51,12 +54,9 @@ class MailNotificationServiceImplTest { @Mock private CoreConfig coreConfig; - @Mock - private UserConnector userConnector; @Mock - private UserRegistryConnector userRegistryConnector; - + private UserApiConnector userApiConnector; @Mock private UserNotificationService userNotificationService; @@ -88,22 +88,13 @@ void sendNotificationDelegationMail() { Institution institution = new Institution(); institution.setId("institutionID"); institution.setDigitalAddress("test@test.com"); - - var mail = new CertifiedField(); - mail.setValue("test@test2.com"); - var work = new WorkContact(); - work.setEmail(mail); - var map = new HashMap(); - map.put("institutionID", work); - var user = new User(); - user.setId("userID"); - user.setWorkContacts(map); + List userEmails = List.of("userEmail"); when(productService.getProduct(anyString())).thenReturn(product); when(institutionConnector.findById(anyString())).thenReturn(institution); - when(userConnector.findUsersByInstitutionIdAndProductId(institution.getId(), product.getId())).thenReturn(List.of(user.getId())); - when(userRegistryConnector.getUserByInternalIdWithCustomFields(user.getId(), "workContacts")).thenReturn(user); + when(userApiConnector.getUserEmails(institution.getId(), product.getId())).thenReturn(userEmails); when(coreConfig.isSendEmailToInstitution()).thenReturn(true); + when(coreConfig.isEnableSendDelegationMail()).thenReturn(true); Assertions.assertDoesNotThrow(() -> notificationService.sendMailForDelegation("institutionName", "productId", "partnerId")); } diff --git a/core/src/test/java/it/pagopa/selfcare/mscore/core/OnboardingServiceImplTest.java b/core/src/test/java/it/pagopa/selfcare/mscore/core/OnboardingServiceImplTest.java index 1e7dd5bc6..e449508f7 100644 --- a/core/src/test/java/it/pagopa/selfcare/mscore/core/OnboardingServiceImplTest.java +++ b/core/src/test/java/it/pagopa/selfcare/mscore/core/OnboardingServiceImplTest.java @@ -30,6 +30,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.context.ContextConfiguration; @@ -107,6 +108,40 @@ void shouldNothingWhenVerifyOnboardingInfoSubunit() { verify(institutionConnector).existsByTaxCodeAndSubunitCodeAndProductAndStatusList(any(), any(), any(), any()); } + @Test + void VerifyOnboardingInfoSubunitResourceNotFound() { + when(institutionConnector.existsByTaxCodeAndSubunitCodeAndProductAndStatusList(any(), any(), any(), any())) + .thenReturn(false); + assertThrows(ResourceNotFoundException.class, () -> onboardingServiceImpl.verifyOnboardingInfoSubunit("42", "42", "example")); + + } + + @Test + void testVerifyOnboardingInfoByFilter() { + // Arrange + when(institutionConnector.existsOnboardingByFilters(Mockito.any())).thenReturn(true); + + VerifyOnboardingFilters verifyOnboardingFilters = new VerifyOnboardingFilters("Product", "", "", "Origin", "OriginId", ""); + // Act + onboardingServiceImpl.verifyOnboardingInfoByFilters(verifyOnboardingFilters); + + // Assert that nothing has changed + verify(institutionConnector).existsOnboardingByFilters(Mockito.any()); + } + + @Test + void testVerifyOnboardingInfoByFilterNotFound() { + // Arrange + when(institutionConnector.existsOnboardingByFilters(Mockito.any())).thenReturn(false); + + VerifyOnboardingFilters verifyOnboardingFilters = new VerifyOnboardingFilters("Product", "", "", "Origin", "OriginId", ""); + // Act + Assertions.assertThrows(ResourceNotFoundException.class, () -> onboardingServiceImpl.verifyOnboardingInfoByFilters(verifyOnboardingFilters)); + + // Assert that nothing has changed + verify(institutionConnector).existsOnboardingByFilters(Mockito.any()); + } + /** * Method under test: {@link OnboardingServiceImpl#verifyOnboardingInfo(String, String)} */ @@ -994,15 +1029,15 @@ private Token getToken(InstitutionUpdate institutionUpdate) { private User dummyUser() { - CertifiedField certifiedField = new CertifiedField<>(); + CertifiedField certifiedField = new CertifiedField<>(); certifiedField.setCertification(Certification.NONE); certifiedField.setValue("42"); - CertifiedField certifiedField1 = new CertifiedField<>(); + CertifiedField certifiedField1 = new CertifiedField<>(); certifiedField1.setCertification(Certification.NONE); certifiedField1.setValue("42"); - CertifiedField certifiedField2 = new CertifiedField<>(); + CertifiedField certifiedField2 = new CertifiedField<>(); certifiedField2.setCertification(Certification.NONE); certifiedField2.setValue("42"); diff --git a/core/src/test/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyTest.java b/core/src/test/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyTest.java index 22bbabbfb..8b969066b 100644 --- a/core/src/test/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyTest.java +++ b/core/src/test/java/it/pagopa/selfcare/mscore/core/strategy/CreateInstitutionStrategyTest.java @@ -45,6 +45,9 @@ class CreateInstitutionStrategyTest { @Spy InstitutionMapper institutionMapper = new InstitutionMapperImpl(); + @InjectMocks + CreateInstitutionStrategyIvass createInstitutionStrategyIvass; + private static final InstitutionProxyInfo dummyInstitutionProxyInfo; private static final CategoryProxyInfo dummyCategoryProxyInfo; @@ -119,6 +122,19 @@ void shouldThrowExceptionOnCreateInstitutionFromIpaIfAlreadyExists() { } + @Test + void shouldThrowMsCoreExceptionWhenInstitutionAlreadyExists() { + String origin = "IVASS"; + String originId = "12345"; + + when(institutionConnector.findByOriginAndOriginId(origin, originId)).thenReturn(List.of(new Institution())); + + assertThrows(ResourceConflictException.class, () -> strategyFactory.createInstitutionStrategyIvass(new Institution()) + .createInstitution(CreateInstitutionStrategyInput.builder() + .ivassCode(originId) + .build())); + } + @Test void shouldThrowExceptionOnCreateInstitutionIfAlreadyExists() { @@ -170,7 +186,7 @@ void shouldCreateInstitutionFromAnac() { void shouldCreateInstitutionFromIvass() { Institution institution = TestUtils.dummyInstitutionAs(); - AsResource asResource = new AsResource(); + ASResource asResource = new ASResource(); asResource.setOriginId("originId"); asResource.setTaxCode("taxCode"); asResource.setDescription("desc"); diff --git a/core/src/test/java/it/pagopa/selfcare/mscore/core/util/TestUtils.java b/core/src/test/java/it/pagopa/selfcare/mscore/core/util/TestUtils.java index 75f8cf50d..b99a593b1 100644 --- a/core/src/test/java/it/pagopa/selfcare/mscore/core/util/TestUtils.java +++ b/core/src/test/java/it/pagopa/selfcare/mscore/core/util/TestUtils.java @@ -44,7 +44,7 @@ private static Institution dummyInstitution(InstitutionType institutionType) { return new Institution("42", "42", Origin.SELC.name(), "START - setupCommonData", "The characteristics of someone or something", institutionType, "42 Main St", "42 Main St", "21654", - "TaxCode", "city", "county", "country", "istatCode", billing, onboarding, geographicTaxonomies, attributes, paymentServiceProvider, + "TaxCode","ivass", "city", "county", "country", "istatCode", billing, onboarding, geographicTaxonomies, attributes, paymentServiceProvider, new DataProtectionOfficer(), null, null, "START - setupCommonData", "START - setupCommonData", "START - setupCommonData", true, OffsetDateTime.now(), OffsetDateTime.now(), null, null, null, null, new PaAttributes(),false); } diff --git a/infra/container_apps/.terraform.lock.hcl b/infra/container_apps/.terraform.lock.hcl index 8baa26205..dd904d6e1 100644 --- a/infra/container_apps/.terraform.lock.hcl +++ b/infra/container_apps/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/azure/azapi" { version = "1.9.0" constraints = "~> 1.9.0" hashes = [ + "h1:Ow1rr5fYBGSkplH/kcXeWz9y2wA81BnhZ7vTBzJfAAg=", "h1:shpEoqcAbf+p6AvspiYO1YrX//8l1LV/owEcQpujWHw=", "zh:349569471fbf387feaaf8b88da1690669e201147c342f905e5eb03df42b3cf87", "zh:54346d5fb78cbad3eb7cfd96e1dd7ce4f78666cabaaccfec6ee9437476330018", @@ -26,6 +27,7 @@ provider "registry.terraform.io/hashicorp/azurerm" { constraints = "<= 3.91.0" hashes = [ "h1:8hMFuaTQsZIV69D0J/W+6hSlhRRDzYSpC0Eg9yWYF0o=", + "h1:Iv9CR+7491iozaK2AkCSAK2u4a2rPyJDQpyHijClj6Y=", "zh:13928b71b1235783f3f877a799e28fb91e50512b051eb8ccb370500fc140cf3f", "zh:3264341657e9ff3963d69b0fa088f64665349e2a29b2f3aeb4deee6d9d7584b7", "zh:467a2ddd2eee26353db65e949bfbe533481ca0fb53c152724380b63a308f11b9", diff --git a/infra/container_apps/env/dev-pnpg/terraform.tfvars b/infra/container_apps/env/dev-pnpg/terraform.tfvars index 63b224e19..af2f0897b 100644 --- a/infra/container_apps/env/dev-pnpg/terraform.tfvars +++ b/infra/container_apps/env/dev-pnpg/terraform.tfvars @@ -168,23 +168,23 @@ app_settings = [ }, { name = "MS_NOTIFICATION_MANAGER_URL" - value = "https://selc-d-pnpg-notification-mngr-ca.yellowdesert-85d3792d.westeurope.azurecontainerapps.io" + value = "https://selc-d-pnpg-notification-mngr-ca.victoriousfield-e39534b8.westeurope.azurecontainerapps.io" }, { name = "USERVICE_PARTY_REGISTRY_PROXY_URL" - value = "https://selc-d-pnpg-party-reg-proxy-ca.yellowdesert-85d3792d.westeurope.azurecontainerapps.io" + value = "https://selc-d-pnpg-party-reg-proxy-ca.victoriousfield-e39534b8.westeurope.azurecontainerapps.io" }, { name = "MS_PRODUCT_URL" - value = "https://selc-d-pnpg-product-ca.yellowdesert-85d3792d.westeurope.azurecontainerapps.io" + value = "https://selc-d-pnpg-product-ca.victoriousfield-e39534b8.westeurope.azurecontainerapps.io" }, { name = "USERVICE_USER_REGISTRY_URL" value = "https://api.uat.pdv.pagopa.it/user-registry/v1" }, { - name = "PRODUCT_STORAGE_CONTAINER" - value = "selc-d-product" + name = "SELFCARE_USER_URL" + value = "https://selc-d-pnpg-user-ms-ca.victoriousfield-e39534b8.westeurope.azurecontainerapps.io" } ] diff --git a/infra/container_apps/env/dev/terraform.tfvars b/infra/container_apps/env/dev/terraform.tfvars index f6130577a..ffef0e252 100644 --- a/infra/container_apps/env/dev/terraform.tfvars +++ b/infra/container_apps/env/dev/terraform.tfvars @@ -188,15 +188,15 @@ app_settings = [ }, { name = "MS_NOTIFICATION_MANAGER_URL" - value = "https://selc-d-notification-mngr-ca.livelydesert-633675bb.westeurope.azurecontainerapps.io" + value = "https://selc-d-notification-mngr-ca.politewater-9af33050.westeurope.azurecontainerapps.io" }, { name = "USERVICE_PARTY_REGISTRY_PROXY_URL" - value = "https://selc-d-party-reg-proxy-ca.livelydesert-633675bb.westeurope.azurecontainerapps.io" + value = "https://selc-d-party-reg-proxy-ca.politewater-9af33050.westeurope.azurecontainerapps.io" }, { name = "MS_PRODUCT_URL" - value = "https://selc-d-product-ca.livelydesert-633675bb.westeurope.azurecontainerapps.io" + value = "https://selc-d-product-ca.politewater-9af33050.westeurope.azurecontainerapps.io" }, { name = "USERVICE_USER_REGISTRY_URL" diff --git a/infra/container_apps/env/prod-pnpg/terraform.tfvars b/infra/container_apps/env/prod-pnpg/terraform.tfvars index 208ed4c5d..509572257 100644 --- a/infra/container_apps/env/prod-pnpg/terraform.tfvars +++ b/infra/container_apps/env/prod-pnpg/terraform.tfvars @@ -163,23 +163,23 @@ app_settings = [ }, { name = "MS_NOTIFICATION_MANAGER_URL" - value = "https://selc-p-pnpg-notification-mngr-ca.redbeach-5da5166f.westeurope.azurecontainerapps.io" + value = "https://selc-p-pnpg-notification-mngr-ca.calmmoss-0be48755.westeurope.azurecontainerapps.io" }, { name = "USERVICE_PARTY_REGISTRY_PROXY_URL" - value = "https://selc-p-pnpg-party-reg-proxy-ca.redbeach-5da5166f.westeurope.azurecontainerapps.io" + value = "https://selc-p-pnpg-party-reg-proxy-ca.calmmoss-0be48755.westeurope.azurecontainerapps.io" }, { name = "MS_PRODUCT_URL" - value = "https://selc-p-pnpg-product-ca.redbeach-5da5166f.westeurope.azurecontainerapps.io" + value = "https://selc-p-pnpg-product-ca.calmmoss-0be48755.westeurope.azurecontainerapps.io" }, { name = "USERVICE_USER_REGISTRY_URL" value = "https://api.pdv.pagopa.it/user-registry/v1" }, { - name = "PRODUCT_STORAGE_CONTAINER" - value = "selc-p-product" + name = "SELFCARE_USER_URL" + value = "https://selc-p-pnpg-user-ms-ca.calmmoss-0be48755.westeurope.azurecontainerapps.io" } ] diff --git a/infra/container_apps/env/prod/terraform.tfvars b/infra/container_apps/env/prod/terraform.tfvars index 248157523..11b38a801 100644 --- a/infra/container_apps/env/prod/terraform.tfvars +++ b/infra/container_apps/env/prod/terraform.tfvars @@ -176,23 +176,23 @@ app_settings = [ }, { name = "MS_NOTIFICATION_MANAGER_URL" - value = "https://selc-p-notification-mngr-ca.salmonstone-7f910b8f.westeurope.azurecontainerapps.io" + value = "https://selc-p-notification-mngr-ca.greensand-62fc96da.westeurope.azurecontainerapps.io" }, { name = "USERVICE_PARTY_REGISTRY_PROXY_URL" - value = "https://selc-p-party-reg-proxy-ca.salmonstone-7f910b8f.westeurope.azurecontainerapps.io" + value = "https://selc-p-party-reg-proxy-ca.greensand-62fc96da.westeurope.azurecontainerapps.io" }, { name = "MS_PRODUCT_URL" - value = "https://selc-p-product-ca.salmonstone-7f910b8f.westeurope.azurecontainerapps.io" + value = "https://selc-p-product-ca.greensand-62fc96da.westeurope.azurecontainerapps.io" }, { name = "USERVICE_USER_REGISTRY_URL" value = "https://api.pdv.pagopa.it/user-registry/v1" }, { - name = "PRODUCT_STORAGE_CONTAINER" - value = "selc-p-product" + name = "SELFCARE_USER_URL" + value = "https://selc-p-user-ms-ca.greensand-62fc96da.westeurope.azurecontainerapps.io" } ] diff --git a/infra/container_apps/env/uat-pnpg/terraform.tfvars b/infra/container_apps/env/uat-pnpg/terraform.tfvars index 791e88680..1160b9249 100644 --- a/infra/container_apps/env/uat-pnpg/terraform.tfvars +++ b/infra/container_apps/env/uat-pnpg/terraform.tfvars @@ -1,5 +1,7 @@ -env_short = "u" -is_pnpg = true +env_short = "u" +is_pnpg = true +suffix_increment = "-001" +cae_name = "cae-001" tags = { CreatedBy = "Terraform" @@ -12,9 +14,9 @@ tags = { container_app = { min_replicas = 1 max_replicas = 2 - scale_rules = [] - cpu = 0.5 - memory = "1Gi" + scale_rules = [] + cpu = 0.5 + memory = "1Gi" } app_settings = [ @@ -154,11 +156,11 @@ app_settings = [ }, { name = "MS_NOTIFICATION_MANAGER_URL" - value = "https://selc-u-pnpg-notification-mngr-ca.calmforest-ffe47bf1.westeurope.azurecontainerapps.io" + value = "https://selc-u-pnpg-notification-mngr-ca.orangeground-0bd2d4dc.westeurope.azurecontainerapps.io" }, { name = "USERVICE_PARTY_REGISTRY_PROXY_URL" - value = "https://selc-u-pnpg-party-reg-proxy-ca.calmforest-ffe47bf1.westeurope.azurecontainerapps.io" + value = "https://selc-u-pnpg-party-reg-proxy-ca.orangeground-0bd2d4dc.westeurope.azurecontainerapps.io" }, { name = "MS_PRODUCT_URL" @@ -169,8 +171,8 @@ app_settings = [ value = "https://api.uat.pdv.pagopa.it/user-registry/v1" }, { - name = "PRODUCT_STORAGE_CONTAINER" - value = "selc-u-product" + name = "SELFCARE_USER_URL" + value = "https://selc-u-pnpg-user-ms-ca.orangeground-0bd2d4dc.westeurope.azurecontainerapps.io" } ] diff --git a/infra/container_apps/env/uat/terraform.tfvars b/infra/container_apps/env/uat/terraform.tfvars index 129a9cf8b..9e2e6d829 100644 --- a/infra/container_apps/env/uat/terraform.tfvars +++ b/infra/container_apps/env/uat/terraform.tfvars @@ -1,4 +1,6 @@ -env_short = "u" +env_short = "u" +suffix_increment = "-001" +cae_name = "cae-001" tags = { CreatedBy = "Terraform" @@ -11,9 +13,9 @@ tags = { container_app = { min_replicas = 1 max_replicas = 2 - scale_rules = [] - cpu = 0.5 - memory = "1Gi" + scale_rules = [] + cpu = 0.5 + memory = "1Gi" } @@ -165,23 +167,23 @@ app_settings = [ }, { name = "MS_NOTIFICATION_MANAGER_URL" - value = "https://selc-u-notification-mngr-ca.agreeablesky-f71e6306.westeurope.azurecontainerapps.io" + value = "https://selc-u-notification-mngr-ca.proudglacier-20652b81.westeurope.azurecontainerapps.io" }, { name = "USERVICE_PARTY_REGISTRY_PROXY_URL" - value = "https://selc-u-party-reg-proxy-ca.agreeablesky-f71e6306.westeurope.azurecontainerapps.io" + value = "https://selc-u-party-reg-proxy-ca.proudglacier-20652b81.westeurope.azurecontainerapps.io" }, { name = "MS_PRODUCT_URL" - value = "https://selc.internal.uat.selfcare.pagopa.it/ms-product/v1" + value = "https://selc-u-product-ca.proudglacier-20652b81.westeurope.azurecontainerapps.io" }, { name = "USERVICE_USER_REGISTRY_URL" value = "https://api.uat.pdv.pagopa.it/user-registry/v1" }, { - name = "PRODUCT_STORAGE_CONTAINER" - value = "selc-u-product" + name = "SELFCARE_USER_URL" + value = "https://selc-u-user-ms-ca.proudglacier-20652b81.westeurope.azurecontainerapps.io" } ] diff --git a/infra/container_apps/locals.tf b/infra/container_apps/locals.tf new file mode 100644 index 000000000..167de2c53 --- /dev/null +++ b/infra/container_apps/locals.tf @@ -0,0 +1,7 @@ +locals { + pnpg_suffix = var.is_pnpg == true ? "-pnpg" : "" + project = "selc-${var.env_short}" + + container_app_environment_name = "${local.project}${local.pnpg_suffix}-${var.cae_name}" + ca_resource_group_name = "${local.project}-container-app${var.suffix_increment}-rg" +} \ No newline at end of file diff --git a/infra/container_apps/main.tf b/infra/container_apps/main.tf index 46c211ba0..8b176ace8 100644 --- a/infra/container_apps/main.tf +++ b/infra/container_apps/main.tf @@ -13,13 +13,16 @@ module "container_app_core" { is_pnpg = var.is_pnpg - env_short = var.env_short - container_app = var.container_app - container_app_name = "ms-core" - image_name = "selfcare-ms-core" - image_tag = var.image_tag - app_settings = var.app_settings - secrets_names = var.secrets_names + env_short = var.env_short + container_app = var.container_app + resource_group_name = local.ca_resource_group_name + container_app_name = "ms-core" + container_app_environment_name = local.container_app_environment_name + image_name = "selfcare-ms-core" + image_tag = var.image_tag + app_settings = var.app_settings + secrets_names = var.secrets_names + workload_profile_name = var.workload_profile_name tags = var.tags } diff --git a/infra/container_apps/variables.tf b/infra/container_apps/variables.tf index a517b090a..bad40e569 100644 --- a/infra/container_apps/variables.tf +++ b/infra/container_apps/variables.tf @@ -54,4 +54,22 @@ variable "app_settings" { variable "secrets_names" { type = map(string) description = "KeyVault secrets to get values from" +} + +variable "workload_profile_name" { + type = string + description = "Workload Profile name to use" + default = null +} + +variable "cae_name" { + type = string + description = "Container App Environment name" + default = "cae-cp" +} + +variable "suffix_increment" { + type = string + description = "Suffix increment Container App Environment name" + default = "" } \ No newline at end of file diff --git a/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/DelegationController.java b/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/DelegationController.java index f01f73e95..b9ebf61f6 100644 --- a/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/DelegationController.java +++ b/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/DelegationController.java @@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.tags.Tags; import it.pagopa.selfcare.mscore.constant.GenericError; import it.pagopa.selfcare.mscore.constant.GetDelegationsMode; +import it.pagopa.selfcare.mscore.constant.Order; import it.pagopa.selfcare.mscore.core.DelegationService; import it.pagopa.selfcare.mscore.exception.InvalidRequestException; import it.pagopa.selfcare.mscore.model.delegation.Delegation; @@ -105,13 +106,15 @@ public ResponseEntity> getDelegations(@ApiParam("${swag @RequestParam(name = "taxCode", required = false) String taxCode, @ApiParam("${swagger.mscore.institutions.delegations.mode}") @RequestParam(name = "mode", required = false) GetDelegationsMode mode, + @ApiParam("${swagger.mscore.institutions.delegations.order}") + @RequestParam(name = "order", required = false) Optional order, @RequestParam(name = "page", required = false) Optional page, @RequestParam(name = "size", required = false) Optional size) { if(Objects.isNull(institutionId) && Objects.isNull(brokerId)) throw new InvalidRequestException("institutionId or brokerId must not be null!!", GenericError.GENERIC_ERROR.getCode()); - return ResponseEntity.status(HttpStatus.OK).body(delegationService.getDelegations(institutionId, brokerId, productId, search, taxCode, mode, page, size).stream() + return ResponseEntity.status(HttpStatus.OK).body(delegationService.getDelegations(institutionId, brokerId, productId, search, taxCode, mode, order, page, size).stream() .map(delegationMapper::toDelegationResponse) .collect(Collectors.toList())); } diff --git a/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/InstitutionController.java b/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/InstitutionController.java index b3de56fc9..3f3aa81ee 100644 --- a/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/InstitutionController.java +++ b/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/InstitutionController.java @@ -353,7 +353,7 @@ public ResponseEntity updateInstitution(@ApiParam("${swagge @ApiOperation(value = "${swagger.mscore.onboarding.users}", notes = "${swagger.mscore.onboarding.users}") @PostMapping(value = "/{id}/onboarding", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity onboardingInstitution(@RequestBody @Valid InstitutionOnboardingRequest request, - @PathVariable("id") String id) { + @PathVariable("id") String id) { CustomExceptionMessage.setCustomMessage(GenericError.ONBOARDING_OPERATION_ERROR); List usersToOnboard = Optional.ofNullable(request.getUsers()) .map(users -> users.stream().map(userMapper::toUserToOnboard).toList()) diff --git a/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/OnboardingController.java b/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/OnboardingController.java index 482771b69..1ed160b67 100644 --- a/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/OnboardingController.java +++ b/web/src/main/java/it/pagopa/selfcare/mscore/web/controller/OnboardingController.java @@ -11,6 +11,7 @@ import it.pagopa.selfcare.mscore.core.OnboardingService; import it.pagopa.selfcare.mscore.model.onboarding.OnboardingInfo; import it.pagopa.selfcare.mscore.model.onboarding.ResourceResponse; +import it.pagopa.selfcare.mscore.model.onboarding.VerifyOnboardingFilters; import it.pagopa.selfcare.mscore.model.user.RelationshipInfo; import it.pagopa.selfcare.mscore.web.model.institution.RelationshipResult; import it.pagopa.selfcare.mscore.web.model.mapper.OnboardingMapper; @@ -74,9 +75,9 @@ public ResponseEntity verifyOnboardingInfo(@ApiParam("${swagger.mscore.ins /** * The function verify onboarding status of given product and subunit of institution * - * @param taxCode String + * @param taxCode String * @param subunitCode String - * @param productId String + * @param productId String * @return no content * * Code: 204, Message: successful operation, DataType: TokenId * * Code: 400, Message: Invalid ID supplied, DataType: Problem @@ -96,6 +97,26 @@ public ResponseEntity verifyOnboardingInfo(@ApiParam("${swagger.mscore.ins return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); } + @ResponseStatus(HttpStatus.NO_CONTENT) + @ApiOperation(value = "${swagger.mscore.onboarding.verify}", notes = "${swagger.mscore.onboarding.verify}") + @RequestMapping(method = {RequestMethod.HEAD}, value = "/verify") + public ResponseEntity verifyOnboardingInfoByFilters(@ApiParam("${swagger.mscore.institutions.model.productId}") + @RequestParam(value = "productId") String productId, + @ApiParam("${swagger.mscore.institutions.model.externalId}") + @RequestParam(value = "externalId", required = false) String externalId, + @ApiParam("${swagger.mscore.institutions.model.taxCode}") + @RequestParam(value = "taxCode", required = false) String taxCode, + @ApiParam("${swagger.mscore.institutions.model.origin}") + @RequestParam(value = "origin", required = false) String origin, + @ApiParam("${swagger.mscore.institutions.model.originId}") + @RequestParam(value = "originId", required = false) String originId, + @ApiParam("${swagger.mscore.institutions.model.subunitCode}") + @RequestParam(value = "subunitCode", required = false) String subunitCode) { + CustomExceptionMessage.setCustomMessage(GenericError.ONBOARDING_VERIFICATION_ERROR); + onboardingService.verifyOnboardingInfoByFilters(new VerifyOnboardingFilters(productId, externalId, taxCode, origin, originId, subunitCode)); + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + /** * The function return onboardingInfo * @@ -180,7 +201,7 @@ public ResponseEntity> onboardingInstitutionSubDelegate @ApiOperation(value = "${swagger.mscore.onboarding.users}", notes = "${swagger.mscore.onboarding.users}") @PostMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> onboardingInstitutionUsers(@RequestBody @Valid OnboardingInstitutionUsersRequest request, - Authentication authentication) { + Authentication authentication) { CustomExceptionMessage.setCustomMessage(GenericError.ONBOARDING_SUBDELEGATES_ERROR); SelfCareUser selfCareUser = (SelfCareUser) authentication.getPrincipal(); List response = onboardingService.onboardingUsers(onboardingResourceMapper.toOnboardingUsersRequest(request), selfCareUser.getUserName(), selfCareUser.getSurname()); diff --git a/web/src/main/java/it/pagopa/selfcare/mscore/web/model/institution/InstitutionRequest.java b/web/src/main/java/it/pagopa/selfcare/mscore/web/model/institution/InstitutionRequest.java index 9130b7efc..3e66e4772 100644 --- a/web/src/main/java/it/pagopa/selfcare/mscore/web/model/institution/InstitutionRequest.java +++ b/web/src/main/java/it/pagopa/selfcare/mscore/web/model/institution/InstitutionRequest.java @@ -4,7 +4,6 @@ import it.pagopa.selfcare.mscore.model.onboarding.OnboardingRequest; import lombok.Data; -import javax.validation.constraints.NotEmpty; import java.time.OffsetDateTime; import java.util.List; @@ -23,9 +22,7 @@ public class InstitutionRequest { private String city; private String county; private String country; - @NotEmpty(message = "TaxCode is required") private String taxCode; - private BillingRequest billing; private List onboarding; private List geographicTaxonomies; diff --git a/web/src/main/java/it/pagopa/selfcare/mscore/web/model/institution/InstitutionResponse.java b/web/src/main/java/it/pagopa/selfcare/mscore/web/model/institution/InstitutionResponse.java index 3ec25b1f9..f87cca22d 100644 --- a/web/src/main/java/it/pagopa/selfcare/mscore/web/model/institution/InstitutionResponse.java +++ b/web/src/main/java/it/pagopa/selfcare/mscore/web/model/institution/InstitutionResponse.java @@ -25,7 +25,6 @@ public class InstitutionResponse { private String digitalAddress; private String address; private String zipCode; - @NotBlank private String taxCode; private String city; private String county; diff --git a/web/src/main/resources/swagger/swagger_en.properties b/web/src/main/resources/swagger/swagger_en.properties index 7f1364f96..45acb0f26 100644 --- a/web/src/main/resources/swagger/swagger_en.properties +++ b/web/src/main/resources/swagger/swagger_en.properties @@ -44,6 +44,8 @@ swagger.mscore.institutions.model.createdAt=The createdAt date swagger.mscore.institutions.model.type=Institution's type swagger.mscore.institutions.model.taxCode=Institution's tax code swagger.mscore.institutions.model.subunitCode=Institution's subunit code +swagger.mscore.institutions.model.origin=Institution's origin +swagger.mscore.institutions.model.originId=Institution's id in the relative origin open data swagger.mscore.onboarding.institution.complete = update institution and users data without adding a new token swagger.mscore.onboarding.institution.persist = Responsible for saving the association between an institution and a product. It also creates occurrences in the Users collection as part of this process. swagger.mscore.onboarding.institution=create a new Token (contract), and update institution and users data @@ -92,6 +94,7 @@ swagger.mscore.api.users.updateUserStatus=Update user status with optional filte swagger.mscore.api.users.getOnboardedUsers=Retrieve onboarded users according to identifiers in input swagger.mscore.institutions.delegations=Retrieve institution's delegations swagger.mscore.institutions.delegations.mode=Mode (full or normal) to retreieve institution's delegations +swagger.mscore.institutions.delegations.order=Order to show response NONE, ASC, DESC swagger.mscore.institutions.brokers=Retrieve institution brokers swagger.mscore.institutions.getInstitutionBrokers=Retrieve institution brokers swagger.mscore.users.userId=User's unique identifier diff --git a/web/src/main/resources/swagger/swagger_it.properties b/web/src/main/resources/swagger/swagger_it.properties index fe3a2a63a..0601e0e87 100644 --- a/web/src/main/resources/swagger/swagger_it.properties +++ b/web/src/main/resources/swagger/swagger_it.properties @@ -26,6 +26,8 @@ swagger.mscore.institutions.model.description=Descrizione ente swagger.mscore.institutions.model.productId=Identificativo univoco del prodotto swagger.mscore.institutions.model.personId=Identificativo univoco dell'utente (UUID) swagger.mscore.institutions.model.institutionId=Identificativo interno dell'institution +swagger.mscore.institutions.model.origin=Identificativo del registro su cui effettuare la ricerca +swagger.mscore.institutions.model.originId=Identificativo dell'ente all'interno degli open data swagger.mscore.institutions.existsInRegistry=boolean per la persistenza delle PG destinatarie (esiste in info camere o AdE) swagger.mscore.institutions.model.relationshipState=Lista di stati per filtrare i prodotti swagger.mscore.institutions.valid=Restituisce la lista di institution per le quali l'utente pu� ancora effettuare l'onboarding diff --git a/web/src/test/java/it/pagopa/selfcare/mscore/web/controller/DelegationControllerTest.java b/web/src/test/java/it/pagopa/selfcare/mscore/web/controller/DelegationControllerTest.java index 4c857730d..4fac97ae0 100644 --- a/web/src/test/java/it/pagopa/selfcare/mscore/web/controller/DelegationControllerTest.java +++ b/web/src/test/java/it/pagopa/selfcare/mscore/web/controller/DelegationControllerTest.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import it.pagopa.selfcare.mscore.constant.DelegationType; import it.pagopa.selfcare.mscore.constant.GetDelegationsMode; +import it.pagopa.selfcare.mscore.constant.Order; import it.pagopa.selfcare.mscore.core.DelegationService; import it.pagopa.selfcare.mscore.model.delegation.Delegation; import it.pagopa.selfcare.mscore.web.model.delegation.DelegationRequest; @@ -130,7 +131,7 @@ void getDelegations_shouldInvalidRequest() { } /** - * Method under test: {@link DelegationController#getDelegations(String, String, String, String, String, GetDelegationsMode, Optional, Optional)} + * Method under test: {@link DelegationController#getDelegations(String, String, String, String, String, GetDelegationsMode, Optional, Optional, Optional)} */ @Test void getDelegations_shouldGetData() throws Exception { @@ -138,7 +139,7 @@ void getDelegations_shouldGetData() throws Exception { Delegation expectedDelegation = dummyDelegation(); when(delegationService.getDelegations(expectedDelegation.getFrom(), expectedDelegation.getTo(), - expectedDelegation.getProductId(), null, null, GetDelegationsMode.NORMAL, Optional.empty(), Optional.empty())) + expectedDelegation.getProductId(), null, null, GetDelegationsMode.NORMAL, Optional.empty(), Optional.empty(), Optional.empty())) .thenReturn(List.of(expectedDelegation)); // When MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders @@ -166,7 +167,7 @@ void getDelegations_shouldGetData() throws Exception { verify(delegationService, times(1)) .getDelegations(expectedDelegation.getFrom(), expectedDelegation.getTo(), - expectedDelegation.getProductId(), null, null, GetDelegationsMode.NORMAL, + expectedDelegation.getProductId(), null, null, GetDelegationsMode.NORMAL, Optional.empty(), Optional.empty(), Optional.empty()); verifyNoMoreInteractions(delegationService); @@ -182,7 +183,7 @@ void getDelegations_shouldGetDataCustom() throws Exception { expectedDelegations.add(delegation2); when(delegationService.getDelegations(null, TO1, - null, null, null, GetDelegationsMode.FULL, Optional.empty(), Optional.empty())) + null, null, null, GetDelegationsMode.FULL, Optional.empty(), Optional.empty(), Optional.empty())) .thenReturn(expectedDelegations); // When MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders @@ -209,13 +210,13 @@ void getDelegations_shouldGetDataCustom() throws Exception { verify(delegationService, times(1)) .getDelegations(null, TO1, null, - null, null, GetDelegationsMode.FULL, + null, null, GetDelegationsMode.FULL, Optional.empty(), Optional.empty(), Optional.empty()); verifyNoMoreInteractions(delegationService); } /** - * Method under test: {@link DelegationController#getDelegations(String, String, String, String, String, GetDelegationsMode, Optional, Optional)} + * Method under test: {@link DelegationController#getDelegations(String, String, String, String, String, GetDelegationsMode, Optional, Optional, Optional)} */ @Test void getDelegations_shouldGetData_nullMode() throws Exception { @@ -223,7 +224,7 @@ void getDelegations_shouldGetData_nullMode() throws Exception { Delegation expectedDelegation = dummyDelegation(); when(delegationService.getDelegations(expectedDelegation.getFrom(), expectedDelegation.getTo(), - expectedDelegation.getProductId(), null, null, null, Optional.empty(), Optional.empty())) + expectedDelegation.getProductId(), null, null, null, Optional.empty(), Optional.empty(), Optional.empty())) .thenReturn(List.of(expectedDelegation)); // When MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders @@ -251,7 +252,7 @@ void getDelegations_shouldGetData_nullMode() throws Exception { verify(delegationService, times(1)) .getDelegations(expectedDelegation.getFrom(), expectedDelegation.getTo(), - expectedDelegation.getProductId(), null, null, null, Optional.empty(), Optional.empty()); + expectedDelegation.getProductId(), null, null, null, Optional.empty(), Optional.empty(), Optional.empty()); verifyNoMoreInteractions(delegationService); } diff --git a/web/src/test/java/it/pagopa/selfcare/mscore/web/controller/OnboardingControllerTest.java b/web/src/test/java/it/pagopa/selfcare/mscore/web/controller/OnboardingControllerTest.java index 78a4d0b79..829bb2f82 100644 --- a/web/src/test/java/it/pagopa/selfcare/mscore/web/controller/OnboardingControllerTest.java +++ b/web/src/test/java/it/pagopa/selfcare/mscore/web/controller/OnboardingControllerTest.java @@ -1,7 +1,6 @@ package it.pagopa.selfcare.mscore.web.controller; import com.fasterxml.jackson.databind.ObjectMapper; -import it.pagopa.selfcare.commons.base.security.PartyRole; import it.pagopa.selfcare.commons.base.security.SelfCareUser; import it.pagopa.selfcare.commons.base.utils.InstitutionType; import it.pagopa.selfcare.mscore.core.OnboardingService; @@ -11,14 +10,8 @@ import it.pagopa.selfcare.mscore.model.institution.InstitutionUpdate; import it.pagopa.selfcare.mscore.model.institution.PaymentServiceProvider; import it.pagopa.selfcare.mscore.model.onboarding.ResourceResponse; -import it.pagopa.selfcare.mscore.web.model.institution.BillingRequest; -import it.pagopa.selfcare.mscore.web.model.institution.DataProtectionOfficerRequest; -import it.pagopa.selfcare.mscore.web.model.institution.InstitutionUpdateRequest; -import it.pagopa.selfcare.mscore.web.model.institution.PaymentServiceProviderRequest; import it.pagopa.selfcare.mscore.web.model.mapper.*; -import it.pagopa.selfcare.mscore.web.model.onboarding.ContractRequest; import it.pagopa.selfcare.mscore.web.model.onboarding.OnboardingInstitutionOperatorsRequest; -import it.pagopa.selfcare.mscore.web.model.onboarding.OnboardingInstitutionRequest; import it.pagopa.selfcare.mscore.web.model.onboarding.OnboardingInstitutionUsersRequest; import it.pagopa.selfcare.mscore.web.model.user.Person; import org.junit.jupiter.api.BeforeEach; @@ -203,52 +196,6 @@ void testGetOnboardingDocument2() throws Exception { .andExpect(MockMvcResultMatchers.content().string("")); } - private OnboardingInstitutionRequest createOnboardingInstitutionRequest() { - BillingRequest billingRequest = new BillingRequest(); - billingRequest.setPublicServices(true); - billingRequest.setRecipientCode("Recipient Code"); - billingRequest.setVatNumber("42"); - - ContractRequest contractRequest = new ContractRequest(); - contractRequest.setPath("Path"); - contractRequest.setVersion("1.0.2"); - - InstitutionUpdateRequest institutionUpdate = new InstitutionUpdateRequest(); - institutionUpdate.setAddress("42 Main St"); - institutionUpdate.setDescription("The characteristics of someone or something"); - institutionUpdate.setDigitalAddress("42 Main St"); - List geographicTaxonomiesList = new ArrayList<>(); - institutionUpdate.setGeographicTaxonomyCodes(geographicTaxonomiesList); - institutionUpdate.setInstitutionType(InstitutionType.GSP); - institutionUpdate.setTaxCode("Tax Code"); - institutionUpdate.setZipCode("21654"); - institutionUpdate.setPaymentServiceProvider(new PaymentServiceProviderRequest()); - institutionUpdate.setDataProtectionOfficer(new DataProtectionOfficerRequest()); - - Person person = new Person(); - person.setId("42"); - person.setName("Name"); - person.setProductRole("Product Role"); - person.setRole(PartyRole.MANAGER); - person.setSurname("Doe"); - person.setTaxCode("Tax Code"); - - ArrayList personList = new ArrayList<>(); - personList.add(person); - - OnboardingInstitutionRequest onboardingInstitutionRequest = new OnboardingInstitutionRequest(); - onboardingInstitutionRequest.setUsers(personList); - onboardingInstitutionRequest.setBilling(billingRequest); - onboardingInstitutionRequest.setContract(contractRequest); - onboardingInstitutionRequest.setInstitutionExternalId("42"); - onboardingInstitutionRequest.setInstitutionUpdate(institutionUpdate); - onboardingInstitutionRequest.setPricingPlan("Pricing Plan"); - onboardingInstitutionRequest.setProductId("42"); - onboardingInstitutionRequest.setProductName("Product Name"); - - return onboardingInstitutionRequest; - } - /** * Method under test: {@link OnboardingController#onboardingInstitutionOperators(OnboardingInstitutionOperatorsRequest, Authentication)} */ @@ -405,6 +352,23 @@ void shouldVerifyOnboardingInfoBySubunit() throws Exception { actualPerformResult.andExpect(MockMvcResultMatchers.status().isNoContent()); } + /** + * Method under test: {@link OnboardingController#verifyOnboardingInfoByFilters(String, String, String, String, String, String)} + */ + @Test + void shouldVerifyOnboardingInfoByFiltersSuccess() throws Exception { + doNothing().when(onboardingService).verifyOnboardingInfoByFilters(any()); + MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders + .head("/onboarding/verify") + .queryParam("origin", "42") + .queryParam("originId", "42") + .queryParam("productId", "42"); + ResultActions actualPerformResult = MockMvcBuilders.standaloneSetup(onboardingController) + .build() + .perform(requestBuilder); + actualPerformResult.andExpect(MockMvcResultMatchers.status().isNoContent()); + } + /** * Method under test: {@link OnboardingController#verifyOnboardingInfo(String, String)} */ @@ -455,5 +419,5 @@ void testOnboardingInfo() throws Exception { .andExpect(MockMvcResultMatchers.status().isOk()); } -} + }