diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/dto/NotificationsResources.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/dto/NotificationsResources.java new file mode 100644 index 000000000..98a06460f --- /dev/null +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/dto/NotificationsResources.java @@ -0,0 +1,51 @@ +package it.pagopa.selfcare.onboarding.dto; + +import it.pagopa.selfcare.onboarding.entity.Onboarding; +import it.pagopa.selfcare.onboarding.entity.Token; +import org.openapi.quarkus.core_json.model.InstitutionResponse; + +public class NotificationsResources { + private Onboarding onboarding; + private InstitutionResponse institution; + private Token token; + private QueueEvent queueEvent; + + public NotificationsResources(Onboarding onboarding, InstitutionResponse institution, Token token, QueueEvent queueEvent) { + this.onboarding = onboarding; + this.institution = institution; + this.token = token; + this.queueEvent = queueEvent; + } + + public Onboarding getOnboarding() { + return onboarding; + } + + public void setOnboarding(Onboarding onboarding) { + this.onboarding = onboarding; + } + + public InstitutionResponse getInstitution() { + return institution; + } + + public void setInstitution(InstitutionResponse institution) { + this.institution = institution; + } + + public Token getToken() { + return token; + } + + public void setToken(Token token) { + this.token = token; + } + + public QueueEvent getQueueEvent() { + return queueEvent; + } + + public void setQueueEvent(QueueEvent queueEvent) { + this.queueEvent = queueEvent; + } +} diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/dto/ResendNotificationsFilters.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/dto/ResendNotificationsFilters.java index 786e17e19..45191ed29 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/dto/ResendNotificationsFilters.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/dto/ResendNotificationsFilters.java @@ -11,14 +11,7 @@ public class ResendNotificationsFilters { private String from; private String to; private Integer page; - - public Integer getPage() { - return page; - } - - public void setPage(Integer page) { - this.page = page; - } + private String notificationEventTraceId; public ResendNotificationsFilters() { } @@ -32,6 +25,7 @@ private ResendNotificationsFilters(Builder builder) { this.from = builder.from; this.to = builder.to; this.page = builder.page; + this.notificationEventTraceId = builder.notificationEventTraceId; } public static Builder builder() { @@ -46,8 +40,8 @@ public static class Builder { private List status; private String from; private String to; - private Integer page; + private String notificationEventTraceId; public Builder productId(String productId) { this.productId = productId; @@ -89,6 +83,11 @@ public Builder page(Integer page) { return this; } + public Builder notificationEventTraceId(String notificationEventTraceId) { + this.notificationEventTraceId = notificationEventTraceId; + return this; + } + public ResendNotificationsFilters build() { return new ResendNotificationsFilters(this); } @@ -150,6 +149,22 @@ public void setTo(String to) { this.to = to; } + public Integer getPage() { + return page; + } + + public void setPage(Integer page) { + this.page = page; + } + + public String getNotificationEventTraceId() { + return notificationEventTraceId; + } + + public void setNotificationEventTraceId(String notificationEventTraceId) { + this.notificationEventTraceId = notificationEventTraceId; + } + @Override public String toString() { return "ResendNotificationsFilters{" + @@ -161,6 +176,7 @@ public String toString() { ", from='" + from + '\'' + ", to='" + to + '\'' + ", page='" + page + '\'' + + ", notificationEventTraceId='" + notificationEventTraceId + '\'' + '}'; } } diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/functions/NotificationFunctions.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/functions/NotificationFunctions.java index dd658fe0d..d9c45eb8d 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/functions/NotificationFunctions.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/functions/NotificationFunctions.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.logging.Level; import static it.pagopa.selfcare.onboarding.functions.CommonFunctions.FORMAT_LOGGER_ONBOARDING_STRING; import static it.pagopa.selfcare.onboarding.functions.utils.ActivityName.*; @@ -53,7 +54,6 @@ public NotificationFunctions(ObjectMapper objectMapper, * It gets invoked by module onboarding-cdc when status is COMPLETED or DELETED */ @FunctionName("Notification") - @FixedDelayRetry(maxRetryCount = 3, delayInterval = "00:00:30") public HttpResponseMessage sendNotification ( @HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage> request, final ExecutionContext context) { @@ -165,9 +165,12 @@ public HttpResponseMessage resendNotifications( @FunctionName("NotificationsSender") public void notificationsSenderOrchestrator( @DurableOrchestrationTrigger(name = "taskOrchestrationContext") TaskOrchestrationContext ctx, - ExecutionContext functionContext) { - String filtersString = ctx.getInput(String.class); - functionContext.getLogger().info("Resend notifications orchestration started with input: " + filtersString); + ExecutionContext functionContext) throws JsonProcessingException { + String filtersString = getFiltersFromContextAndEnrichWithInstanceId(ctx); + if (functionContext.getLogger().isLoggable(Level.INFO)) { + functionContext.getLogger().info("Resend notifications orchestration started with input: " + filtersString); + } + do { filtersString = ctx.callActivity(RESEND_NOTIFICATIONS_ACTIVITY, filtersString, String.class).await(); } while (filtersString != null); @@ -175,6 +178,22 @@ public void notificationsSenderOrchestrator( functionContext.getLogger().info("Resend notifications orchestration completed"); } + /** + * It retrieves the filters from the orchestrator context and enriches them with the instanceId. + * For logging purposes, the instanceId will be used as the notificationEventTraceId. + * + * @param ctx TaskOrchestrationContext provided by the Azure Functions runtime. + * @return JSON string representing the filters to be applied when resending notifications. + * @throws JsonProcessingException if there is an error parsing the filtersString into a ResendNotificationsFilters object. + */ + private String getFiltersFromContextAndEnrichWithInstanceId(TaskOrchestrationContext ctx) throws JsonProcessingException { + String filtersString = ctx.getInput(String.class); + String instanceId = ctx.getInstanceId(); + ResendNotificationsFilters filters = objectMapper.readValue(filtersString, ResendNotificationsFilters.class); + filters.setNotificationEventTraceId(instanceId); + return objectMapper.writeValueAsString(filters); + } + /** * It is triggered by the orchestrator function "NotificationsSender", and is responsible for a resend of single page of notifications. * @@ -186,7 +205,6 @@ public void notificationsSenderOrchestrator( @FunctionName(RESEND_NOTIFICATIONS_ACTIVITY) public String resendNotificationsActivity(@DurableActivityTrigger(name = "filtersString") String filtersString, final ExecutionContext context) throws JsonProcessingException { context.getLogger().info(() -> String.format(FORMAT_LOGGER_ONBOARDING_STRING, RESEND_NOTIFICATIONS_ACTIVITY, filtersString)); - ResendNotificationsFilters filters; try { filters = objectMapper.readValue(filtersString, ResendNotificationsFilters.class); @@ -197,7 +215,7 @@ public String resendNotificationsActivity(@DurableActivityTrigger(name = "filter /* * At the end of the resendNotifications it is checked whether there are more onboardings to resend, if there are, the method * returns the same filters received as input by incrementing the page by one to fetch on next iteration the next page of onboardings. - * Otherwise it returns null. + * Otherwise, it returns null. */ ResendNotificationsFilters nextFilters = notificationEventResenderService.resendNotifications(filters, context); diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/functions/OnboardingFunctions.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/functions/OnboardingFunctions.java index 7c12a1a9d..aeb4e577d 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/functions/OnboardingFunctions.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/functions/OnboardingFunctions.java @@ -189,31 +189,31 @@ public void saveToken(@DurableActivityTrigger(name = "onboardingString") String @FunctionName(SEND_MAIL_REGISTRATION_FOR_CONTRACT) public void sendMailRegistrationForContract(@DurableActivityTrigger(name = "onboardingString") String onboardingWorkflowString, final ExecutionContext context) { context.getLogger().info(String.format(FORMAT_LOGGER_ONBOARDING_STRING, SEND_MAIL_REGISTRATION_FOR_CONTRACT, onboardingWorkflowString)); - service.sendMailRegistrationForContract(readOnboardingWorkflowValue(objectMapper, onboardingWorkflowString)); + service.sendMailRegistrationForContract(context, readOnboardingWorkflowValue(objectMapper, onboardingWorkflowString)); } @FunctionName(SEND_MAIL_REGISTRATION_FOR_CONTRACT_WHEN_APPROVE_ACTIVITY) public void sendMailRegistrationForContractWhenApprove(@DurableActivityTrigger(name = "onboardingString") String onboardingWorkflowString, final ExecutionContext context) { context.getLogger().info(String.format(FORMAT_LOGGER_ONBOARDING_STRING, SEND_MAIL_REGISTRATION_FOR_CONTRACT_WHEN_APPROVE_ACTIVITY, onboardingWorkflowString)); - service.sendMailRegistrationForContractWhenApprove(readOnboardingWorkflowValue(objectMapper, onboardingWorkflowString)); + service.sendMailRegistrationForContractWhenApprove(context, readOnboardingWorkflowValue(objectMapper, onboardingWorkflowString)); } @FunctionName(SEND_MAIL_REGISTRATION_REQUEST_ACTIVITY) public void sendMailRegistration(@DurableActivityTrigger(name = "onboardingString") String onboardingString, final ExecutionContext context) { context.getLogger().info(String.format(FORMAT_LOGGER_ONBOARDING_STRING, SEND_MAIL_REGISTRATION_REQUEST_ACTIVITY, onboardingString)); - service.sendMailRegistration(readOnboardingValue(objectMapper, onboardingString)); + service.sendMailRegistration(context, readOnboardingValue(objectMapper, onboardingString)); } @FunctionName(SEND_MAIL_REGISTRATION_APPROVE_ACTIVITY) public void sendMailRegistrationApprove(@DurableActivityTrigger(name = "onboardingString") String onboardingString, final ExecutionContext context) { context.getLogger().info(String.format(FORMAT_LOGGER_ONBOARDING_STRING, SEND_MAIL_REGISTRATION_APPROVE_ACTIVITY, onboardingString)); - service.sendMailRegistrationApprove(readOnboardingValue(objectMapper, onboardingString)); + service.sendMailRegistrationApprove(context, readOnboardingValue(objectMapper, onboardingString)); } @FunctionName(SEND_MAIL_ONBOARDING_APPROVE_ACTIVITY) public void sendMailOnboardingApprove(@DurableActivityTrigger(name = "onboardingString") String onboardingString, final ExecutionContext context) { context.getLogger().info(String.format(FORMAT_LOGGER_ONBOARDING_STRING, SEND_MAIL_ONBOARDING_APPROVE_ACTIVITY, onboardingString)); - service.sendMailOnboardingApprove(readOnboardingValue(objectMapper, onboardingString)); + service.sendMailOnboardingApprove(context, readOnboardingValue(objectMapper, onboardingString)); } @FunctionName(CREATE_INSTITUTION_ACTIVITY) @@ -237,13 +237,13 @@ public void storeOnboardingActivatedAt(@DurableActivityTrigger(name = "onboardin @FunctionName(SEND_MAIL_COMPLETION_ACTIVITY) public void sendMailCompletion(@DurableActivityTrigger(name = "onboardingString") String onboardingWorkflowString, final ExecutionContext context) { context.getLogger().info(String.format(FORMAT_LOGGER_ONBOARDING_STRING, SEND_MAIL_COMPLETION_ACTIVITY, onboardingWorkflowString)); - completionService.sendCompletedEmail(readOnboardingWorkflowValue(objectMapper, onboardingWorkflowString)); + completionService.sendCompletedEmail(context, readOnboardingWorkflowValue(objectMapper, onboardingWorkflowString)); } @FunctionName(SEND_MAIL_REJECTION_ACTIVITY) public void sendMailRejection(@DurableActivityTrigger(name = "onboardingString") String onboardingString, final ExecutionContext context) { context.getLogger().info(String.format(FORMAT_LOGGER_ONBOARDING_STRING, SEND_MAIL_REJECTION_ACTIVITY, onboardingString)); - completionService.sendMailRejection(readOnboardingValue(objectMapper, onboardingString)); + completionService.sendMailRejection(context, readOnboardingValue(objectMapper, onboardingString)); } @FunctionName(CREATE_USERS_ACTIVITY) @@ -255,7 +255,7 @@ public void createOnboardedUsers(@DurableActivityTrigger(name = "onboardingStrin @FunctionName(SEND_MAIL_COMPLETION_AGGREGATE_ACTIVITY) public void sendMailCompletionAggregate(@DurableActivityTrigger(name = "onboardingString") String onboardingString, final ExecutionContext context) { context.getLogger().info(String.format(FORMAT_LOGGER_ONBOARDING_STRING, SEND_MAIL_COMPLETION_AGGREGATE_ACTIVITY, onboardingString)); - completionService.sendCompletedEmailAggregate(readOnboardingValue(objectMapper, onboardingString)); + completionService.sendCompletedEmailAggregate(context, readOnboardingValue(objectMapper, onboardingString)); } @FunctionName(CREATE_AGGREGATE_ONBOARDING_REQUEST_ACTIVITY) @@ -274,11 +274,11 @@ public String createDelegationForAggregation(@DurableActivityTrigger(name = "onb * After that, It sends a message on topics through the event bus */ @FunctionName("TestSendEmail") - public HttpResponseMessage sendTestEmail( + public void sendTestEmail( @HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage> request, final ExecutionContext context) { context.getLogger().info("TestSendEmail trigger processed a request"); completionService.sendTestEmail(context); - return request.createResponseBuilder(HttpStatus.OK).build(); + request.createResponseBuilder(HttpStatus.OK).build(); } } diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/CompletionService.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/CompletionService.java index 89d99dc60..ffd2244d5 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/CompletionService.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/CompletionService.java @@ -9,15 +9,15 @@ public interface CompletionService { String createInstitutionAndPersistInstitutionId(Onboarding onboarding); - void sendMailRejection(Onboarding onboarding); + void sendMailRejection(ExecutionContext context, Onboarding onboarding); void persistOnboarding(Onboarding onboarding); void persistActivatedAt(Onboarding onboarding); - void sendCompletedEmail(OnboardingWorkflow onboardingWorkflow); + void sendCompletedEmail(ExecutionContext context, OnboardingWorkflow onboardingWorkflow); - void sendCompletedEmailAggregate(Onboarding onboarding); + void sendCompletedEmailAggregate(ExecutionContext context, Onboarding onboarding); void persistUsers(Onboarding onboarding); diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/CompletionServiceDefault.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/CompletionServiceDefault.java index 958d58267..13d65dc16 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/CompletionServiceDefault.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/CompletionServiceDefault.java @@ -43,6 +43,7 @@ import static it.pagopa.selfcare.onboarding.common.WorkflowType.CONFIRMATION_AGGREGATE; import static it.pagopa.selfcare.onboarding.service.NotificationEventServiceDefault.*; import static it.pagopa.selfcare.onboarding.service.OnboardingService.USERS_FIELD_LIST; +import static it.pagopa.selfcare.onboarding.utils.Utils.TelemetryConstants.*; import static jakarta.ws.rs.core.Response.Status.Family.SUCCESSFUL; @ApplicationScoped @@ -70,8 +71,6 @@ public class CompletionServiceDefault implements CompletionService { @Inject org.openapi.quarkus.party_registry_proxy_json.api.InstitutionApi institutionRegistryProxyApi; - private static final String EVENT_SEND_COMPLETION_FN_FAILURE = "EventsSendCompletionEmail_failures"; - private final InstitutionMapper institutionMapper; private final OnboardingRepository onboardingRepository; private final TokenRepository tokenRepository; @@ -82,7 +81,6 @@ public class CompletionServiceDefault implements CompletionService { private final OnboardingMapper onboardingMapper; private final TelemetryClient telemetryClient; private final boolean hasToSendEmail; - private final boolean isEmailServiceAvailable; private final boolean forceInstitutionCreation; public CompletionServiceDefault(ProductService productService, @@ -93,7 +91,6 @@ public CompletionServiceDefault(ProductService productService, InstitutionMapper institutionMapper, OnboardingRepository onboardingRepository, TokenRepository tokenRepository, - @ConfigProperty(name = "onboarding-functions.email.service.available") boolean isEmailServiceAvailable, @ConfigProperty(name = "onboarding-functions.persist-users.send-mail") boolean hasToSendEmail, @ConfigProperty(name = "onboarding-functions.force-institution-persist")boolean forceInstitutionCreation, @Context @ConfigProperty(name = "onboarding-functions.appinsights.connection-string") String appInsightsConnectionString) { @@ -107,7 +104,6 @@ public CompletionServiceDefault(ProductService productService, this.onboardingMapper = onboardingMapper; this.userMapper = userMapper; this.productMapper = productMapper; - this.isEmailServiceAvailable = isEmailServiceAvailable; this.hasToSendEmail = hasToSendEmail; this.forceInstitutionCreation = forceInstitutionCreation; this.telemetryClient = new TelemetryClient(telemetryConfiguration); @@ -116,130 +112,51 @@ public CompletionServiceDefault(ProductService productService, @Override public String createInstitutionAndPersistInstitutionId(Onboarding onboarding) { - InstitutionResponse institutionResponse; - //When onboarding a pg institution this condition ensures that the institution's informations are persisted correctly - if(forceInstitutionCreation){ - institutionResponse = createInstitution(onboarding.getInstitution()); - }else { - Institution institution = onboarding.getInstitution(); - InstitutionsResponse institutionsResponse = getInstitutions(institution); - if (Objects.nonNull(institutionsResponse.getInstitutions()) && institutionsResponse.getInstitutions().size() > 1) { - throw new GenericOnboardingException("List of institutions is ambiguous, it is empty or has more than one element!!"); - } - - institutionResponse = - Objects.isNull(institutionsResponse.getInstitutions()) || institutionsResponse.getInstitutions().isEmpty() - ? createInstitution(institution) - : institutionsResponse.getInstitutions().get(0); + InstitutionResponse institutionResponse = createOrRetrieveInstitution(onboarding); + if (Objects.nonNull(institutionResponse)) { onboardingRepository .update("institution.id = ?1 and updatedAt = ?2 ", institutionResponse.getId(), LocalDateTime.now()) .where("_id", onboarding.getId()); - + return institutionResponse.getId(); } - return institutionResponse.getId(); - } - - private InstitutionsResponse getInstitutions(Institution institution) { - InstitutionsResponse institutionsResponse; - if(StringUtils.isNotBlank(institution.getTaxCode())) { - institutionsResponse = institutionApi.getInstitutionsUsingGET(institution.getTaxCode(), institution.getSubunitCode(), null, null); - } else { - String origin = Objects.nonNull(institution.getOrigin()) ? institution.getOrigin().getValue() : null; - institutionsResponse = institutionApi.getInstitutionsUsingGET(null, null, origin, institution.getOriginId()); - } - return institutionsResponse; + throw new GenericOnboardingException("Error when create institutions!"); } - /** - * Function that creates institution based on institution type and Origin, - * Origin indicates which is the indexes where data come from, for ex. IPA comes from index of Pubbliche Amministrazioni - * Look at ... for more information about institution type and indexes - */ - private InstitutionResponse createInstitution(Institution institution) { - - if(InstitutionType.SA.equals(institution.getInstitutionType()) - && Origin.ANAC.equals(institution.getOrigin())) { - - return institutionApi.createInstitutionFromAnacUsingPOST(institutionMapper.toInstitutionRequest(institution)); + public InstitutionResponse createOrRetrieveInstitution(Onboarding onboarding) { + if (forceInstitutionCreation) { + //When onboarding a pg institution this condition ensures that the institution's informations are persisted correctly + return createInstitution(onboarding.getInstitution()); } - if(InstitutionType.AS.equals(institution.getInstitutionType()) - && Origin.IVASS.equals(institution.getOrigin())) { + Institution institution = onboarding.getInstitution(); + InstitutionsResponse institutionsResponse = getInstitutions(institution); - return institutionApi.createInstitutionFromIvassUsingPOST(institutionMapper.toInstitutionRequest(institution)); - } - - if(InstitutionType.PG.equals(institution.getInstitutionType()) && - (Origin.INFOCAMERE.equals(institution.getOrigin()) || Origin.ADE.equals(institution.getOrigin()))) { - - return institutionApi.createInstitutionFromInfocamereUsingPOST(institutionMapper.toInstitutionRequest(institution)); + if (Objects.nonNull(institutionsResponse.getInstitutions()) && institutionsResponse.getInstitutions().size() > 1) { + throw new GenericOnboardingException("List of institutions is ambiguous, it is empty or has more than one element!!"); } - if(isInstitutionPresentOnIpa(institution)) { - - InstitutionFromIpaPost fromIpaPost = new InstitutionFromIpaPost(); - fromIpaPost.setTaxCode(institution.getTaxCode()); - fromIpaPost.setGeographicTaxonomies(Optional.ofNullable(institution.getGeographicTaxonomies()) - .map(geographicTaxonomies -> geographicTaxonomies.stream().map(institutionMapper::toGeographicTaxonomy).toList()) - .orElse(List.of())); - fromIpaPost.setInstitutionType(InstitutionFromIpaPost.InstitutionTypeEnum.valueOf(institution.getInstitutionType().name())); - if(Objects.nonNull(institution.getSubunitType())) { - fromIpaPost.setSubunitCode(institution.getSubunitCode()); - fromIpaPost.setSubunitType(InstitutionFromIpaPost.SubunitTypeEnum.valueOf(institution.getSubunitType().name())); - } - return institutionApi.createInstitutionFromIpaUsingPOST(fromIpaPost); - } - - return institutionApi.createInstitutionUsingPOST(institutionMapper.toInstitutionRequest(institution)); - } - - private boolean isInstitutionPresentOnIpa(Institution institution) { - try { - if (InstitutionPaSubunitType.AOO.equals(institution.getSubunitType())) { - aooApi.findByUnicodeUsingGET(institution.getSubunitCode(), null); - } else if (InstitutionPaSubunitType.UO.equals(institution.getSubunitType())) { - uoApi.findByUnicodeUsingGET1(institution.getSubunitCode(), null); - } else { - institutionRegistryProxyApi.findInstitutionUsingGET(institution.getTaxCode(), null, null); - } - return true; - } catch (WebApplicationException e) { - if(e.getResponse().getStatus() == 404) { - return false; - } - throw new RuntimeException(e); - } + return + Objects.isNull(institutionsResponse.getInstitutions()) || institutionsResponse.getInstitutions().isEmpty() + ? createInstitution(institution) + : institutionsResponse.getInstitutions().get(0); } @Override - public void sendCompletedEmail(OnboardingWorkflow onboardingWorkflow) { + public void sendCompletedEmail(ExecutionContext context, OnboardingWorkflow onboardingWorkflow) { Onboarding onboarding = onboardingWorkflow.getOnboarding(); - - List destinationMails = onboarding.getUsers().stream() - .filter(userToOnboard -> MANAGER.equals(userToOnboard.getRole())) - .map(userToOnboard -> Optional.ofNullable(userRegistryApi.findByIdUsingGET(USERS_FIELD_LIST, userToOnboard.getId())) - .filter(userResource -> Objects.nonNull(userResource.getWorkContacts()) - && userResource.getWorkContacts().containsKey(userToOnboard.getUserMailUuid())) - .map(user -> user.getWorkContacts().get(userToOnboard.getUserMailUuid())) - ) - .filter(Optional::isPresent) - .map(Optional::get) - .filter(workContract -> StringUtils.isNotBlank(workContract.getEmail().getValue())) - .map(workContract -> workContract.getEmail().getValue()) - .collect(Collectors.toList()); - + List destinationMails = getDestinationMails(onboarding); destinationMails.add(onboarding.getInstitution().getDigitalAddress()); - Product product = productService.getProductIsValid(onboarding.getProductId()); - - if (isEmailServiceAvailable) { + try { notificationService.sendCompletedEmail(onboarding.getInstitution().getDescription(), destinationMails, product, onboarding.getInstitution().getInstitutionType(), onboardingWorkflow); - } else { - telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_COMPLETION_FN_FAILURE, 1D)); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_COMPLETION_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_COMPLETION_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send completion email for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); } } @@ -270,28 +187,19 @@ public String createDelegation(Onboarding onboarding) { } } - private static DelegationRequest getDelegationRequest(Onboarding onboarding) { - DelegationRequest delegationRequest = new DelegationRequest(); - delegationRequest.setProductId(onboarding.getProductId()); - delegationRequest.setType(DelegationRequest.TypeEnum.EA); - delegationRequest.setInstitutionFromName(onboarding.getInstitution().getDescription()); - delegationRequest.setFrom(onboarding.getInstitution().getId()); - delegationRequest.setTo(onboarding.getAggregator().getId()); - delegationRequest.setInstitutionToName(onboarding.getAggregator().getDescription()); - return delegationRequest; - } - @Override - public void sendMailRejection(Onboarding onboarding) { - - List destinationMails = new ArrayList<>(); - destinationMails.add(onboarding.getInstitution().getDigitalAddress()); - + public void sendMailRejection(ExecutionContext context, Onboarding onboarding) { + List destinationMails = Collections.singletonList(onboarding.getInstitution().getDigitalAddress()); Product product = productService.getProductIsValid(onboarding.getProductId()); - notificationService.sendMailRejection(destinationMails, product, onboarding.getReasonForReject()); + try { + notificationService.sendMailRejection(destinationMails, product, onboarding.getReasonForReject()); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_REJECTION_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_REJECTION_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send rejection email for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + } } - @Override public void persistOnboarding(Onboarding onboarding) { //Prepare data for request @@ -328,25 +236,16 @@ public void persistActivatedAt(Onboarding onboarding) { } @Override - public void sendCompletedEmailAggregate(Onboarding onboarding) { - - List destinationMails = onboarding.getUsers().stream() - .filter(userToOnboard -> MANAGER.equals(userToOnboard.getRole())) - .map(userToOnboard -> Optional.ofNullable(userRegistryApi.findByIdUsingGET(USERS_FIELD_LIST, userToOnboard.getId())) - .filter(userResource -> Objects.nonNull(userResource.getWorkContacts()) - && userResource.getWorkContacts().containsKey(userToOnboard.getUserMailUuid())) - .map(user -> user.getWorkContacts().get(userToOnboard.getUserMailUuid())) - ) - .filter(Optional::isPresent) - .map(Optional::get) - .filter(workContract -> StringUtils.isNotBlank(workContract.getEmail().getValue())) - .map(workContract -> workContract.getEmail().getValue()) - .collect(Collectors.toList()); - + public void sendCompletedEmailAggregate(ExecutionContext context, Onboarding onboarding) { + List destinationMails = getDestinationMails(onboarding); destinationMails.add(onboarding.getInstitution().getDigitalAddress()); - - notificationService.sendCompletedEmailAggregate(onboarding.getAggregator().getDescription(), - destinationMails); + try { + notificationService.sendCompletedEmailAggregate(onboarding.getAggregator().getDescription(), destinationMails); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_COMPLETION_AGGREGATE_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_COMPLETION_AGGREGATE_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send completion aggregate email for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + } } @Override @@ -360,6 +259,117 @@ public String createAggregateOnboardingRequest(OnboardingAggregateOrchestratorIn @Override public void sendTestEmail(ExecutionContext context) { - notificationService.sendTestEmail(context); + notificationService.sendTestEmail(context); + } + + private static DelegationRequest getDelegationRequest(Onboarding onboarding) { + DelegationRequest delegationRequest = new DelegationRequest(); + delegationRequest.setProductId(onboarding.getProductId()); + delegationRequest.setType(DelegationRequest.TypeEnum.EA); + delegationRequest.setInstitutionFromName(onboarding.getInstitution().getDescription()); + delegationRequest.setFrom(onboarding.getInstitution().getId()); + delegationRequest.setTo(onboarding.getAggregator().getId()); + delegationRequest.setInstitutionToName(onboarding.getAggregator().getDescription()); + return delegationRequest; + } + + private void setGSPCategory(InstitutionRequest institutionRequest) { + AttributesRequest category = new AttributesRequest(); + category.setCode("L37"); + category.setDescription("Gestori di Pubblici Servizi"); + institutionRequest.setAttributes(List.of(category)); + } + + private boolean isInstitutionPresentOnIpa(Institution institution) { + try { + if (InstitutionPaSubunitType.AOO.equals(institution.getSubunitType())) { + aooApi.findByUnicodeUsingGET(institution.getSubunitCode(), null); + } else if (InstitutionPaSubunitType.UO.equals(institution.getSubunitType())) { + uoApi.findByUnicodeUsingGET1(institution.getSubunitCode(), null); + } else { + institutionRegistryProxyApi.findInstitutionUsingGET(institution.getTaxCode(), null, null); + } + return true; + } catch (WebApplicationException e) { + if(e.getResponse().getStatus() == 404) { + return false; + } + throw new RuntimeException(e); + } + } + + private InstitutionsResponse getInstitutions(Institution institution) { + InstitutionsResponse institutionsResponse; + + if(StringUtils.isNotBlank(institution.getTaxCode())) { + institutionsResponse = institutionApi.getInstitutionsUsingGET(institution.getTaxCode(), institution.getSubunitCode(), null, null); + } else { + String origin = Objects.nonNull(institution.getOrigin()) ? institution.getOrigin().getValue() : null; + institutionsResponse = institutionApi.getInstitutionsUsingGET(null, null, origin, institution.getOriginId()); + } + return institutionsResponse; + } + + /** + * Function that creates institution based on institution type and Origin, + * Origin indicates which is the indexes where data come from, for ex. IPA comes from index of Pubbliche Amministrazioni + * Look at ... for more information about institution type and indexes + */ + private InstitutionResponse createInstitution(Institution institution) { + + if(InstitutionType.SA.equals(institution.getInstitutionType()) + && Origin.ANAC.equals(institution.getOrigin())) { + + return institutionApi.createInstitutionFromAnacUsingPOST(institutionMapper.toInstitutionRequest(institution)); + } + + if(InstitutionType.AS.equals(institution.getInstitutionType()) + && Origin.IVASS.equals(institution.getOrigin())) { + + return institutionApi.createInstitutionFromIvassUsingPOST(institutionMapper.toInstitutionRequest(institution)); + } + + if(InstitutionType.PG.equals(institution.getInstitutionType()) && + (Origin.INFOCAMERE.equals(institution.getOrigin()) || Origin.ADE.equals(institution.getOrigin()))) { + + return institutionApi.createInstitutionFromInfocamereUsingPOST(institutionMapper.toInstitutionRequest(institution)); + } + + if(isInstitutionPresentOnIpa(institution)) { + + InstitutionFromIpaPost fromIpaPost = new InstitutionFromIpaPost(); + fromIpaPost.setTaxCode(institution.getTaxCode()); + fromIpaPost.setGeographicTaxonomies(Optional.ofNullable(institution.getGeographicTaxonomies()) + .map(geographicTaxonomies -> geographicTaxonomies.stream().map(institutionMapper::toGeographicTaxonomy).toList()) + .orElse(List.of())); + fromIpaPost.setInstitutionType(InstitutionFromIpaPost.InstitutionTypeEnum.valueOf(institution.getInstitutionType().name())); + if(Objects.nonNull(institution.getSubunitType())) { + fromIpaPost.setSubunitCode(institution.getSubunitCode()); + fromIpaPost.setSubunitType(InstitutionFromIpaPost.SubunitTypeEnum.valueOf(institution.getSubunitType().name())); + } + return institutionApi.createInstitutionFromIpaUsingPOST(fromIpaPost); + } + + InstitutionRequest institutionRequest = institutionMapper.toInstitutionRequest(institution); + // Override category in case of GSP not present in IPA + if (InstitutionType.GSP.equals(institution.getInstitutionType()) && !Origin.IPA.equals(institution.getOrigin())) { + setGSPCategory(institutionRequest); + } + return institutionApi.createInstitutionUsingPOST(institutionMapper.toInstitutionRequest(institution)); + } + + private List getDestinationMails(Onboarding onboarding) { + return onboarding.getUsers().stream() + .filter(userToOnboard -> MANAGER.equals(userToOnboard.getRole())) + .map(userToOnboard -> Optional.ofNullable(userRegistryApi.findByIdUsingGET(USERS_FIELD_LIST, userToOnboard.getId())) + .filter(userResource -> Objects.nonNull(userResource.getWorkContacts()) + && userResource.getWorkContacts().containsKey(userToOnboard.getUserMailUuid())) + .map(user -> user.getWorkContacts().get(userToOnboard.getUserMailUuid())) + ) + .filter(Optional::isPresent) + .map(Optional::get) + .filter(workContract -> StringUtils.isNotBlank(workContract.getEmail().getValue())) + .map(workContract -> workContract.getEmail().getValue()) + .collect(Collectors.toList()); } } diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventResenderServiceDefault.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventResenderServiceDefault.java index 43d2c74d7..82fbb39e7 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventResenderServiceDefault.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventResenderServiceDefault.java @@ -3,20 +3,18 @@ import com.microsoft.azure.functions.ExecutionContext; import it.pagopa.selfcare.onboarding.dto.ResendNotificationsFilters; import it.pagopa.selfcare.onboarding.entity.Onboarding; -import it.pagopa.selfcare.onboarding.exception.NotificationException; import jakarta.enterprise.context.ApplicationScoped; import java.util.List; import java.util.Optional; -import java.util.logging.Level; @ApplicationScoped public class NotificationEventResenderServiceDefault implements NotificationEventResenderService { private final NotificationEventService notificationEventService; private final OnboardingService onboardingService; - private static final String RESEND_ENDING_LOG = "Resend notifications for page %s completed with %s notifications sent successfully and %s notifications not sent"; - private static final String RESEND_ENDING_LOG_LAST_PAGE = "There aren't more notifications to resend, page %s completed with %s notifications sent successfully and %s notifications not sent"; + private static final String RESEND_ENDING_LOG = "Resend notifications for page %s completed"; + private static final String RESEND_ENDING_LOG_LAST_PAGE = "There aren't more notifications to resend, page %s completed"; public NotificationEventResenderServiceDefault(NotificationEventService notificationEventService, OnboardingService onboardingService) { @@ -25,32 +23,23 @@ public NotificationEventResenderServiceDefault(NotificationEventService notifica } public ResendNotificationsFilters resendNotifications(ResendNotificationsFilters filters, ExecutionContext context) { - context.getLogger().info("resendNotifications started with filters: " + filters.toString()); + context.getLogger().info(() -> "resendNotifications started with filters: " + filters); int page = Optional.ofNullable(filters.getPage()).orElse(0); int pageSize = 100; - int notificationsSent = 0; - int notificationsFailed = 0; List onboardingsToResend = onboardingService.getOnboardingsToResend(filters, page, pageSize); - context.getLogger().info(String.format("Found: %s onboardings to send for page: %s ", onboardingsToResend.size(), page)); - + context.getLogger().info(() -> String.format("Found: %s onboardings to send for page: %s ", onboardingsToResend.size(), page)); for (Onboarding onboarding : onboardingsToResend) { - try { - notificationEventService.send(context, onboarding, null); - notificationsSent++; - } catch (NotificationException e) { - context.getLogger().log(Level.WARNING, e, () -> String.format("Error resending notification for onboarding with ID %s. Error: %s", onboarding.getId(), e.getMessage())); - notificationsFailed++; - } + notificationEventService.send(context, onboarding, null, filters.getNotificationEventTraceId()); } if(onboardingsToResend.isEmpty() || onboardingsToResend.size() < pageSize) { - context.getLogger().info(String.format(RESEND_ENDING_LOG_LAST_PAGE, filters.getPage(), notificationsSent, notificationsFailed)); + context.getLogger().info(() -> String.format(RESEND_ENDING_LOG_LAST_PAGE, filters.getPage())); return null; } - context.getLogger().info(String.format(RESEND_ENDING_LOG, filters.getPage(), notificationsSent, notificationsFailed)); + context.getLogger().info(() -> String.format(RESEND_ENDING_LOG, filters.getPage())); filters.setPage(page + 1); return filters; diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventService.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventService.java index 852b8d04f..22d496aa9 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventService.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventService.java @@ -7,4 +7,6 @@ public interface NotificationEventService { void send(ExecutionContext context, Onboarding onboarding, QueueEvent queueEvent); + + void send(ExecutionContext context, Onboarding onboarding, QueueEvent queueEvent, String notificationEventTraceId); } diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventServiceDefault.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventServiceDefault.java index 240492208..4a9d6a010 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventServiceDefault.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationEventServiceDefault.java @@ -10,6 +10,7 @@ import it.pagopa.selfcare.onboarding.client.eventhub.EventHubRestClient; import it.pagopa.selfcare.onboarding.config.NotificationConfig; import it.pagopa.selfcare.onboarding.dto.NotificationToSend; +import it.pagopa.selfcare.onboarding.dto.NotificationsResources; import it.pagopa.selfcare.onboarding.dto.QueueEvent; import it.pagopa.selfcare.onboarding.entity.Onboarding; import it.pagopa.selfcare.onboarding.entity.Token; @@ -37,7 +38,6 @@ public class NotificationEventServiceDefault implements NotificationEventService public static final String EVENT_ONBOARDING_FN_NAME = "ONBOARDING-FN"; public static final String EVENT_ONBOARDING_INSTTITUTION_FN_FAILURE = "EventsOnboardingInstitution_failures"; - public static final String EVENT_ONBOARDING_INSTTITUTION_FN_ERROR = "EventsOnboardingInstitution_error"; public static final String EVENT_ONBOARDING_INSTTITUTION_FN_SUCCESS = "EventsOnboardingInstitution_success"; public static final String OPERATION_NAME = "ONBOARDING-FN"; private final TelemetryClient telemetryClient; @@ -76,12 +76,19 @@ public NotificationEventServiceDefault(ProductService productService, } public void send(ExecutionContext context, Onboarding onboarding, QueueEvent queueEvent) { + this.send(context, onboarding, queueEvent, null); + } + + @Override + public void send(ExecutionContext context, Onboarding onboarding, QueueEvent queueEvent, String notificationEventTraceId) { + context.getLogger().info(() -> String.format("Starting send method for onboarding with ID %s", onboarding.getId())); if(isNotInstitutionOnboarding(onboarding)) { context.getLogger().info(() -> String.format("Onboarding with ID %s doesn't refer to an institution onboarding, skipping send notification", onboarding.getId())); return; } try { + context.getLogger().info(() -> String.format("Getting product info for onboarding with ID %s and productId %s", onboarding.getId(), onboarding.getProductId())); Product product = productService.getProduct(onboarding.getProductId()); if (product.getConsumers() == null || product.getConsumers().isEmpty()) { context.getLogger().warning(() -> String.format("Node consumers is null or empty for product with ID %s", onboarding.getProductId())); @@ -92,50 +99,52 @@ public void send(ExecutionContext context, Onboarding onboarding, QueueEvent que queueEvent = queueEventExaminer.determineEventType(onboarding); } + context.getLogger().info(() -> String.format("Retrieving institution having ID %s", onboarding.getInstitution().getId())); InstitutionResponse institution = institutionApi.retrieveInstitutionByIdUsingGET(onboarding.getInstitution().getId()); - Optional token = tokenRepository.findByOnboardingId(onboarding.getId()); + + Token token = tokenRepository.findByOnboardingId(onboarding.getId()).orElse(null); + NotificationsResources notificationsResources = new NotificationsResources(onboarding, institution, token, queueEvent); for (String consumer : product.getConsumers()) { NotificationConfig.Consumer consumerConfig = notificationConfig.consumers().get(consumer.toLowerCase()); - prepareAndSendNotification(context, product, consumerConfig, onboarding, token.orElse(null), institution, queueEvent); + prepareAndSendNotification(context, product, consumerConfig, notificationsResources, notificationEventTraceId); } } catch (Exception e) { - telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_ONBOARDING_INSTTITUTION_FN_ERROR, 1D)); - context.getLogger().severe(String.format("Impossible to send notification for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); - throw new NotificationException(String.format("Impossible to send notification for onboarding with ID %s", onboarding.getId()), e); + context.getLogger().severe(String.format("Error sending notification for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e, notificationEventTraceId), Map.of(EVENT_ONBOARDING_INSTTITUTION_FN_FAILURE, 1D)); } } - private void prepareAndSendNotification(ExecutionContext context, Product product, NotificationConfig.Consumer consumer, Onboarding onboarding, Token token, InstitutionResponse institution, QueueEvent queueEvent) throws JsonProcessingException { + private void prepareAndSendNotification(ExecutionContext context, Product product, NotificationConfig.Consumer consumer, NotificationsResources notificationsResources, String notificationEventTraceId) throws JsonProcessingException { NotificationBuilder notificationBuilder = notificationBuilderFactory.create(consumer); - if (notificationBuilder.shouldSendNotification(onboarding, institution)) { - NotificationToSend notificationToSend = notificationBuilder.buildNotificationToSend(onboarding, token, institution, queueEvent); - sendNotification(context, consumer.topic(), notificationToSend); - sendTestEnvProductsNotification(context, product, consumer.topic(), notificationToSend); + if (notificationBuilder.shouldSendNotification(notificationsResources.getOnboarding(), notificationsResources.getInstitution())) { + NotificationToSend notificationToSend = notificationBuilder.buildNotificationToSend(notificationsResources.getOnboarding(), notificationsResources.getToken(), notificationsResources.getInstitution(), notificationsResources.getQueueEvent()); + sendNotification(context, consumer.topic(), notificationToSend, notificationEventTraceId); + sendTestEnvProductsNotification(context, product, consumer.topic(), notificationToSend, notificationEventTraceId); } else { - context.getLogger().info(() -> String.format("Notification not sent for onboarding %s on topic %s", onboarding.getId(), consumer.topic())); + context.getLogger().info(() -> String.format("It was not necessary to send a notification on the topic %s because the onboarding with ID %s did not pass filter verification", notificationsResources.getOnboarding().getId(), consumer.topic())); } } - private void sendNotification(ExecutionContext context, String topic, NotificationToSend notificationToSend) throws JsonProcessingException { + private void sendNotification(ExecutionContext context, String topic, NotificationToSend notificationToSend, String notificationEventTraceId) throws JsonProcessingException { String message = mapper.writeValueAsString(notificationToSend); context.getLogger().info(() -> String.format("Sending notification on topic: %s with message: %s", topic, message)); try { eventHubRestClient.sendMessage(topic, message); - telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, notificationEventMap(notificationToSend, topic), Map.of(EVENT_ONBOARDING_INSTTITUTION_FN_SUCCESS, 1D)); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, notificationEventMap(notificationToSend, topic, notificationEventTraceId), Map.of(EVENT_ONBOARDING_INSTTITUTION_FN_SUCCESS, 1D)); } catch (Exception e) { - telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, notificationEventMap(notificationToSend, topic), Map.of(EVENT_ONBOARDING_INSTTITUTION_FN_FAILURE, 1D)); throw new NotificationException(e.getMessage()); } } - private void sendTestEnvProductsNotification(ExecutionContext context, Product product, String topic, NotificationToSend notificationToSend) throws JsonProcessingException { + private void sendTestEnvProductsNotification(ExecutionContext context, Product product, String topic, NotificationToSend notificationToSend, String notificationEventTraceId) throws JsonProcessingException { + context.getLogger().info(() -> String.format("Starting sendTestEnvProductsNotification with testEnv %s", product.getTestEnvProductIds())); if (product.getTestEnvProductIds() != null) { for (String testEnvProductId : product.getTestEnvProductIds()) { context.getLogger().info(() -> String.format("Notification for onboarding with id: %s should be sent on topic: %s for envProduct : %s", notificationToSend.getOnboardingTokenId(), topic, testEnvProductId)); notificationToSend.setId(UUID.randomUUID().toString()); notificationToSend.setProduct(testEnvProductId); - sendNotification(context, topic, notificationToSend); + sendNotification(context, topic, notificationToSend, notificationEventTraceId); } } } @@ -146,9 +155,21 @@ public static Map onboardingEventMap(Onboarding onboarding) { return propertiesMap; } - public static Map notificationEventMap(NotificationToSend notificationToSend, String topic) { + public static Map onboardingEventFailureMap(Onboarding onboarding, Exception e) { + return onboardingEventFailureMap(onboarding, e, null); + } + + public static Map onboardingEventFailureMap(Onboarding onboarding, Exception e, String notificationEventTraceId) { + Map propertiesMap = onboardingEventMap(onboarding); + Optional.ofNullable(notificationEventTraceId).ifPresent(value -> propertiesMap.put("notificationEventTraceId", value)); + Optional.ofNullable(e).ifPresent(value -> propertiesMap.put("error", Arrays.toString(e.getStackTrace()))); + return propertiesMap; + } + + public static Map notificationEventMap(NotificationToSend notificationToSend, String topic, String notificationEventTraceId) { Map propertiesMap = new HashMap<>(); Optional.ofNullable(topic).ifPresent(value -> propertiesMap.put("topic", value)); + Optional.ofNullable(notificationEventTraceId).ifPresent(value -> propertiesMap.put("notificationEventTraceId", value)); Optional.ofNullable(notificationToSend.getId()).ifPresent(value -> propertiesMap.put("id", value)); Optional.ofNullable(notificationToSend.getInternalIstitutionID()).ifPresent(value -> propertiesMap.put("internalIstitutionID", value)); Optional.ofNullable(notificationToSend.getInstitutionId()).ifPresent(value -> propertiesMap.put("institutionId", value)); diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationServiceDefault.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationServiceDefault.java index 037230c51..26289dcc6 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationServiceDefault.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/NotificationServiceDefault.java @@ -30,7 +30,6 @@ public class NotificationServiceDefault implements NotificationService { private static final Logger log = LoggerFactory.getLogger(NotificationServiceDefault.class); - public static final String PAGOPA_LOGO_FILENAME = "pagopa-logo.png"; private final MailTemplatePlaceholdersConfig templatePlaceholdersConfig; private final MailTemplatePathConfig templatePathConfig; @@ -40,16 +39,18 @@ public class NotificationServiceDefault implements NotificationService { private final String senderMail; private final Boolean destinationMailTest; private final String destinationMailTestAddress; - private final String notificationAdminMail; private final Mailer mailer; + private final boolean isEmailServiceAvailable; + public NotificationServiceDefault(MailTemplatePlaceholdersConfig templatePlaceholdersConfig, MailTemplatePathConfig templatePathConfig, AzureBlobClient azureBlobClient, ObjectMapper objectMapper, Mailer mailer, ContractService contractService, @ConfigProperty(name = "onboarding-functions.notification-admin-email") String notificationAdminMail, @ConfigProperty(name = "onboarding-functions.sender-mail") String senderMail, @ConfigProperty(name = "onboarding-functions.destination-mail-test") Boolean destinationMailTest, - @ConfigProperty(name = "onboarding-functions.destination-mail-test-address") String destinationMailTestAddress) { + @ConfigProperty(name = "onboarding-functions.destination-mail-test-address") String destinationMailTestAddress, + @ConfigProperty(name = "onboarding-functions.email.service.available") boolean isEmailServiceAvailable) { this.templatePlaceholdersConfig = templatePlaceholdersConfig; this.templatePathConfig = templatePathConfig; this.azureBlobClient = azureBlobClient; @@ -60,6 +61,7 @@ public NotificationServiceDefault(MailTemplatePlaceholdersConfig templatePlaceho this.destinationMailTestAddress = destinationMailTestAddress; this.notificationAdminMail = notificationAdminMail; this.mailer = mailer; + this.isEmailServiceAvailable = isEmailServiceAvailable; } @Override @@ -222,7 +224,7 @@ private void sendMailWithFile(List destinationMail, String templateName, mail.addAttachment(fileMailData.name, fileMailData.data, fileMailData.contentType); } - mailer.send(mail); + send(mail); log.info("End of sending mail to {}, with subject {}", destination, subject); } catch (Exception e) { @@ -231,6 +233,12 @@ private void sendMailWithFile(List destinationMail, String templateName, } } + private void send(Mail mail) { + if (isEmailServiceAvailable) { + mailer.send(mail); + } + } + static class FileMailData { byte[] data; String name; @@ -246,7 +254,7 @@ public void sendTestEmail(ExecutionContext context) { .withHtml(senderMail, html, html) .setFrom(senderMail); - mailer.send(mail); + send(mail); context.getLogger().info("End of sending mail to {}, with subject " + senderMail + " with subject " + mail); } catch (Exception e) { context.getLogger().severe(String.format("%s: %s", ERROR_DURING_SEND_MAIL, e.getMessage())); diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingService.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingService.java index b4f40a54f..e72e55a4a 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingService.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingService.java @@ -1,5 +1,7 @@ package it.pagopa.selfcare.onboarding.service; +import com.microsoft.applicationinsights.TelemetryClient; +import com.microsoft.applicationinsights.TelemetryConfiguration; import com.microsoft.azure.functions.ExecutionContext; import eu.europa.esig.dss.enumerations.DigestAlgorithm; import eu.europa.esig.dss.model.DSSDocument; @@ -22,7 +24,9 @@ import it.pagopa.selfcare.product.service.ProductService; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import jakarta.ws.rs.core.Context; import org.bson.Document; +import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.openapi.quarkus.user_registry_json.api.UserApi; import org.openapi.quarkus.user_registry_json.model.CertifiableFieldResourceOfstring; @@ -34,20 +38,18 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; +import static it.pagopa.selfcare.onboarding.service.NotificationEventServiceDefault.*; import static it.pagopa.selfcare.onboarding.utils.Utils.ALLOWED_WORKFLOWS_FOR_INSTITUTION_NOTIFICATIONS; import static it.pagopa.selfcare.onboarding.utils.Utils.CONTRACT_FILENAME_FUNC; +import static it.pagopa.selfcare.onboarding.utils.Utils.TelemetryConstants.*; @ApplicationScoped public class OnboardingService { private static final Logger log = LoggerFactory.getLogger(OnboardingService.class); - public static final String USERS_FIELD_LIST = "fiscalCode,familyName,name"; public static final String USERS_WORKS_FIELD_LIST = "fiscalCode,familyName,name,workContacts"; public static final String USER_REQUEST_DOES_NOT_FOUND = "User request does not found for onboarding %s"; @@ -61,22 +63,33 @@ public class OnboardingService { UserApi userRegistryApi; @Inject NotificationService notificationService; - @Inject - ContractService contractService; - @Inject - ProductService productService; - - @Inject - OnboardingRepository repository; - - @Inject - TokenRepository tokenRepository; - - @Inject - MailTemplatePathConfig mailTemplatePathConfig; - - @Inject - MailTemplatePlaceholdersConfig mailTemplatePlaceholdersConfig; + private final ContractService contractService; + private final ProductService productService; + private final OnboardingRepository repository; + private final TokenRepository tokenRepository; + private final MailTemplatePathConfig mailTemplatePathConfig; + private final MailTemplatePlaceholdersConfig mailTemplatePlaceholdersConfig; + private final TelemetryClient telemetryClient; + public OnboardingService(ProductService productService, + ContractService contractService, + OnboardingRepository repository, + MailTemplatePathConfig mailTemplatePathConfig, + MailTemplatePlaceholdersConfig mailTemplatePlaceholdersConfig, + TokenRepository tokenRepository, + NotificationService notificationService, + @Context @ConfigProperty(name = "onboarding-functions.appinsights.connection-string") String appInsightsConnectionString) { + this.contractService = contractService; + this.repository = repository; + this.tokenRepository = tokenRepository; + TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.createDefault(); + telemetryConfiguration.setConnectionString(appInsightsConnectionString); + this.productService = productService; + this.notificationService = notificationService; + this.mailTemplatePathConfig = mailTemplatePathConfig; + this.mailTemplatePlaceholdersConfig = mailTemplatePlaceholdersConfig; + this.telemetryClient = new TelemetryClient(telemetryConfiguration); + this.telemetryClient.getContext().getOperation().setName(OPERATION_NAME); + } public Optional getOnboarding(String onboardingId) { return repository.findByIdOptional(onboardingId); @@ -144,74 +157,95 @@ private void saveToken(OnboardingWorkflow onboardingWorkflow, Product product, S tokenRepository.persist(token); } - public void sendMailRegistration(Onboarding onboarding) { - + public void sendMailRegistration(ExecutionContext context, Onboarding onboarding) { SendMailInput sendMailInput = builderWithProductAndUserRequest(onboarding); - - notificationService.sendMailRegistration(onboarding.getInstitution().getDescription(), - onboarding.getInstitution().getDigitalAddress(), - sendMailInput.userRequestName, sendMailInput.userRequestSurname, - sendMailInput.product.getTitle()); - + try { + notificationService.sendMailRegistration(onboarding.getInstitution().getDescription(), + onboarding.getInstitution().getDigitalAddress(), + sendMailInput.userRequestName, sendMailInput.userRequestSurname, + sendMailInput.product.getTitle()); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_REGISTRATION_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_REGISTRATION_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send registration email for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + } } - public void sendMailRegistrationForContract(OnboardingWorkflow onboardingWorkflow) { - + public void sendMailRegistrationForContract(ExecutionContext context, OnboardingWorkflow onboardingWorkflow) { Onboarding onboarding = onboardingWorkflow.getOnboarding(); SendMailInput sendMailInput = builderWithProductAndUserRequest(onboarding); - final String templatePath = onboardingWorkflow.emailRegistrationPath(mailTemplatePathConfig); final String confirmTokenUrl = onboardingWorkflow.getConfirmTokenUrl(mailTemplatePlaceholdersConfig); - - notificationService.sendMailRegistrationForContract(onboarding.getId(), - onboarding.getInstitution().getDigitalAddress(), - sendMailInput, - templatePath, - confirmTokenUrl); + try { + notificationService.sendMailRegistrationForContract(onboarding.getId(), + onboarding.getInstitution().getDigitalAddress(), + sendMailInput, + templatePath, + confirmTokenUrl); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_REGISTRATION_CONTRACT_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_REGISTRATION_CONTRACT_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send registration contract email for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + } } - public void sendMailRegistrationForContractAggregator(Onboarding onboarding) { - + public void sendMailRegistrationForContractAggregator(ExecutionContext context, Onboarding onboarding) { SendMailInput sendMailInput = builderWithProductAndUserRequest(onboarding); - - notificationService.sendMailRegistrationForContractAggregator(onboarding.getId(), - onboarding.getInstitution().getDigitalAddress(), - sendMailInput.userRequestName, sendMailInput.userRequestSurname, - sendMailInput.product.getTitle()); + try { + notificationService.sendMailRegistrationForContractAggregator(onboarding.getId(), + onboarding.getInstitution().getDigitalAddress(), + sendMailInput.userRequestName, sendMailInput.userRequestSurname, + sendMailInput.product.getTitle()); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_REGISTRATION_AGGREGATOR_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_REGISTRATION_AGGREGATOR_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send registration contract aggregator email for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + } } - public void sendMailRegistrationForContractWhenApprove(OnboardingWorkflow onboardingWorkflow) { - + public void sendMailRegistrationForContractWhenApprove(ExecutionContext context, OnboardingWorkflow onboardingWorkflow) { Onboarding onboarding = onboardingWorkflow.getOnboarding(); Product product = productService.getProduct(onboarding.getProductId()); - - notificationService.sendMailRegistrationForContract(onboarding.getId(), - onboarding.getInstitution().getDigitalAddress(), - onboarding.getInstitution().getDescription(), "", - product.getTitle(), "description", - onboardingWorkflow.emailRegistrationPath(mailTemplatePathConfig), - onboardingWorkflow.getConfirmTokenUrl(mailTemplatePlaceholdersConfig)); + try { + notificationService.sendMailRegistrationForContract(onboarding.getId(), + onboarding.getInstitution().getDigitalAddress(), + onboarding.getInstitution().getDescription(), "", + product.getTitle(), "description", + onboardingWorkflow.emailRegistrationPath(mailTemplatePathConfig), + onboardingWorkflow.getConfirmTokenUrl(mailTemplatePlaceholdersConfig)); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_REGISTRATION_CONTRACT_APPROVE_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_REGISTRATION_CONTRACT_APPROVE_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send registration contract email in case of approve for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + } } - public void sendMailRegistrationApprove(Onboarding onboarding) { - + public void sendMailRegistrationApprove(ExecutionContext context, Onboarding onboarding) { SendMailInput sendMailInput = builderWithProductAndUserRequest(onboarding); - - notificationService.sendMailRegistrationApprove(onboarding.getInstitution().getDescription(), - sendMailInput.userRequestName, sendMailInput.userRequestSurname, - sendMailInput.product.getTitle(), - onboarding.getId()); - + try { + notificationService.sendMailRegistrationApprove(onboarding.getInstitution().getDescription(), + sendMailInput.userRequestName, sendMailInput.userRequestSurname, + sendMailInput.product.getTitle(), + onboarding.getId()); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_REGISTRATION_APPROVE_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_REGISTRATION_APPROVE_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send registration approve email for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + } } - public void sendMailOnboardingApprove(Onboarding onboarding) { - + public void sendMailOnboardingApprove(ExecutionContext context, Onboarding onboarding) { SendMailInput sendMailInput = builderWithProductAndUserRequest(onboarding); - - notificationService.sendMailOnboardingApprove(onboarding.getInstitution().getDescription(), - sendMailInput.userRequestName, sendMailInput.userRequestSurname, - sendMailInput.product.getTitle(), - onboarding.getId()); + try { + notificationService.sendMailOnboardingApprove(onboarding.getInstitution().getDescription(), + sendMailInput.userRequestName, sendMailInput.userRequestSurname, + sendMailInput.product.getTitle(), + onboarding.getId()); + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventMap(onboarding), Map.of(EVENT_SEND_ONBOARDING_APPROVE_FN_SUCCESS, 1D)); + } catch (Exception e) { + telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e), Map.of(EVENT_SEND_ONBOARDING_APPROVE_FN_FAILURE, 1D)); + context.getLogger().severe(String.format("Impossible to send approve email for onboarding with ID %s %s", onboarding.getId(), Arrays.toString(e.getStackTrace()))); + } } public String getValidManagerId(List users) { @@ -289,11 +323,11 @@ private Document createQuery(String productId, List status, St Document query = new Document(); query.append("productId", productId); query.append("status", new Document("$in", status.stream().map(OnboardingStatus::name).toList())); - if (workflowTypeExist) { - query.append(WORKFLOW_TYPE, new Document("$in", ALLOWED_WORKFLOWS_FOR_INSTITUTION_NOTIFICATIONS.stream().map(Enum::name).toList())); - } else { - query.append(WORKFLOW_TYPE, new Document("$exists", false)); - } + if (workflowTypeExist) { + query.append(WORKFLOW_TYPE, new Document("$in", ALLOWED_WORKFLOWS_FOR_INSTITUTION_NOTIFICATIONS.stream().map(Enum::name).toList())); + } else { + query.append(WORKFLOW_TYPE, new Document("$exists", false)); + } Document dateQuery = new Document(); Optional.ofNullable(from).ifPresent(value -> query.append(dateField, dateQuery.append("$gte", LocalDate.parse(from, DateTimeFormatter.ISO_LOCAL_DATE)))); Optional.ofNullable(to).ifPresent(value -> query.append(dateField, dateQuery.append("$lte", LocalDate.parse(to, DateTimeFormatter.ISO_LOCAL_DATE)))); diff --git a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/utils/Utils.java b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/utils/Utils.java index 3f46b6838..e06742571 100644 --- a/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/utils/Utils.java +++ b/apps/onboarding-functions/src/main/java/it/pagopa/selfcare/onboarding/utils/Utils.java @@ -22,6 +22,28 @@ public class Utils { private Utils() { } + public static class TelemetryConstants { + private TelemetryConstants() { } + public static final String EVENT_SEND_REGISTRATION_FN_FAILURE = "EventsSendRegistrationEmail_failures"; + public static final String EVENT_SEND_REGISTRATION_FN_SUCCESS = "EventsSendRegistrationEmail_success"; + public static final String EVENT_SEND_REGISTRATION_CONTRACT_FN_FAILURE = "EventsSendRegistrationContractEmail_failures"; + public static final String EVENT_SEND_REGISTRATION_CONTRACT_FN_SUCCESS = "EventsSendRegistrationContractEmail_success"; + public static final String EVENT_SEND_ONBOARDING_APPROVE_FN_FAILURE = "EventsSendOnboardingApproveEmail_failures"; + public static final String EVENT_SEND_ONBOARDING_APPROVE_FN_SUCCESS = "EventsSendOnboardingApproveEmail_success"; + public static final String EVENT_SEND_REGISTRATION_APPROVE_FN_FAILURE = "EventsSendRegistrationApproveEmail_failures"; + public static final String EVENT_SEND_REGISTRATION_APPROVE_FN_SUCCESS = "EventsSendRegistrationApproveEmail_success"; + public static final String EVENT_SEND_REGISTRATION_AGGREGATOR_FN_FAILURE = "EventsSendRegistrationAggregatorEmail_failures"; + public static final String EVENT_SEND_REGISTRATION_AGGREGATOR_FN_SUCCESS = "EventsSendRegistrationAggregatorEmail_success"; + public static final String EVENT_SEND_REGISTRATION_CONTRACT_APPROVE_FN_FAILURE = "EventsSendRegistrationContractApproveEmail_failures"; + public static final String EVENT_SEND_REGISTRATION_CONTRACT_APPROVE_FN_SUCCESS = "EventsSendRegistrationContractApproveEmail_success"; + public static final String EVENT_SEND_COMPLETION_FN_FAILURE = "EventsSendCompletionEmail_failures"; + public static final String EVENT_SEND_COMPLETION_FN_SUCCESS = "EventsSendCompletionEmail_success"; + public static final String EVENT_SEND_REJECTION_FN_FAILURE = "EventsSendRejectionEmail_failures"; + public static final String EVENT_SEND_REJECTION_FN_SUCCESS = "EventsSendRejectionEmail_success"; + public static final String EVENT_SEND_COMPLETION_AGGREGATE_FN_SUCCESS = "EventsSendCompletionAggregateEmail_success"; + public static final String EVENT_SEND_COMPLETION_AGGREGATE_FN_FAILURE = "EventsSendCompletionAggregateEmail_failures"; + } + public static final BinaryOperator CONTRACT_FILENAME_FUNC = (filename, productName) -> String.format(filename, StringUtils.stripAccents(productName.replaceAll("\\s+","_"))); diff --git a/apps/onboarding-functions/src/main/resources/application.properties b/apps/onboarding-functions/src/main/resources/application.properties index be555064e..cf1ecab16 100644 --- a/apps/onboarding-functions/src/main/resources/application.properties +++ b/apps/onboarding-functions/src/main/resources/application.properties @@ -39,6 +39,10 @@ onboarding-functions.force-institution-persist= ${FORCE_INSTITUTION_PERSIST:fals ## REST CLIENT # +quarkus.rest-client.logging.scope=request-response +quarkus.rest-client.logging.body-limit=50 + +quarkus.log.category."org.jboss.resteasy.reactive.client.logging".level=INFO quarkus.openapi-generator.user_registry_json.auth.api_key.api-key = ${USER_REGISTRY_API_KEY:example-api-key} quarkus.rest-client."org.openapi.quarkus.user_registry_json.api.UserApi".url=${USER_REGISTRY_URL:http://localhost:8080} diff --git a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/functions/NotificationFunctionsTest.java b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/functions/NotificationFunctionsTest.java index 67762d7d1..c62ee2076 100644 --- a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/functions/NotificationFunctionsTest.java +++ b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/functions/NotificationFunctionsTest.java @@ -335,18 +335,20 @@ void resendNotification_shouldThrowBadRequestWhenFieldsDateHaveWrongFormat() thr } @Test - void notificationsSenderOrchestrator_invokeActivity() { + void notificationsSenderOrchestrator_invokeActivity() throws JsonProcessingException { TaskOrchestrationContext orchestrationContext = mock(TaskOrchestrationContext.class); String filtersString = "{\"productId\":\"prod-pagoPa\", \"status\":[\"COMPLETED\"]}"; when(orchestrationContext.getInput(String.class)).thenReturn(filtersString); - Task task = mock(Task.class); - when(orchestrationContext.callActivity(RESEND_NOTIFICATIONS_ACTIVITY, filtersString, String.class)).thenReturn(task); + when(orchestrationContext.getInstanceId()).thenReturn("instanceId"); + String enrichedFiltersString = "{\"productId\":\"prod-pagoPa\",\"status\":[\"COMPLETED\"],\"notificationEventTraceId\":\"instanceId\"}"; + + when(orchestrationContext.callActivity(RESEND_NOTIFICATIONS_ACTIVITY, enrichedFiltersString, String.class)).thenReturn(task); when(task.await()).thenReturn(null); function.notificationsSenderOrchestrator(orchestrationContext, executionContext); Mockito.verify(orchestrationContext, times(1)) - .callActivity(RESEND_NOTIFICATIONS_ACTIVITY, filtersString, String.class); + .callActivity(RESEND_NOTIFICATIONS_ACTIVITY, enrichedFiltersString, String.class); } @Test diff --git a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/functions/OnboardingFunctionsTest.java b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/functions/OnboardingFunctionsTest.java index 1a5089a3c..736fc5d73 100644 --- a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/functions/OnboardingFunctionsTest.java +++ b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/functions/OnboardingFunctionsTest.java @@ -18,9 +18,7 @@ import it.pagopa.selfcare.onboarding.entity.Institution; import it.pagopa.selfcare.onboarding.entity.Onboarding; import it.pagopa.selfcare.onboarding.exception.ResourceNotFoundException; -import it.pagopa.selfcare.onboarding.mapper.OnboardingMapper; import it.pagopa.selfcare.onboarding.service.CompletionService; -import it.pagopa.selfcare.onboarding.service.NotificationEventService; import it.pagopa.selfcare.onboarding.service.OnboardingService; import jakarta.inject.Inject; import org.junit.jupiter.api.Assertions; @@ -57,12 +55,6 @@ public class OnboardingFunctionsTest { @InjectMock CompletionService completionService; - @InjectMock - NotificationEventService notificationEventService; - - @Inject - OnboardingMapper onboardingMapper; - final String onboardinString = "{\"onboardingId\":\"onboardingId\"}"; final String onboardingWorkflowString = "{\"type\":\"INSTITUTION\",\"onboarding\":{\"id\":\"id\",\"productId\":null,\"testEnvProductIds\":null,\"workflowType\":null,\"institution\":null,\"users\":null,\"aggregates\":null,\"pricingPlan\":null,\"billing\":null,\"signContract\":null,\"expiringDate\":null,\"status\":null,\"userRequestUid\":null,\"workflowInstanceId\":null,\"createdAt\":null,\"updatedAt\":null,\"activatedAt\":null,\"deletedAt\":null,\"reasonForReject\":null,\"isAggregator\":null}}"; @@ -569,12 +561,12 @@ void saveToken() { void sendMailRegistrationWithContract() { when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - doNothing().when(service).sendMailRegistrationForContract(any()); + doNothing().when(service).sendMailRegistrationForContract(any(), any()); function.sendMailRegistrationForContract(onboardingWorkflowString, executionContext); verify(service, times(1)) - .sendMailRegistrationForContract(any()); + .sendMailRegistrationForContract(any(), any()); } @@ -582,48 +574,48 @@ void sendMailRegistrationWithContract() { void sendMailRegistration() { when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - doNothing().when(service).sendMailRegistration(any()); + doNothing().when(service).sendMailRegistration(any(), any()); function.sendMailRegistration(onboardinString, executionContext); verify(service, times(1)) - .sendMailRegistration(any()); + .sendMailRegistration(any(), any()); } @Test void sendMailRegistrationApprove() { when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - doNothing().when(service).sendMailRegistrationApprove(any()); + doNothing().when(service).sendMailRegistrationApprove(any(), any()); function.sendMailRegistrationApprove(onboardinString, executionContext); verify(service, times(1)) - .sendMailRegistrationApprove(any()); + .sendMailRegistrationApprove(any(), any()); } @Test void sendMailOnboardingApprove() { when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - doNothing().when(service).sendMailOnboardingApprove(any()); + doNothing().when(service).sendMailOnboardingApprove(any(), any()); function.sendMailOnboardingApprove(onboardinString, executionContext); verify(service, times(1)) - .sendMailOnboardingApprove(any()); + .sendMailOnboardingApprove(any(), any()); } @Test void sendMailRegistrationWithContractWhenApprove() { when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - doNothing().when(service).sendMailRegistrationForContractWhenApprove(any()); + doNothing().when(service).sendMailRegistrationForContractWhenApprove(any(), any()); function.sendMailRegistrationForContractWhenApprove(onboardingWorkflowString, executionContext); verify(service, times(1)) - .sendMailRegistrationForContractWhenApprove(any()); + .sendMailRegistrationForContractWhenApprove(any(), any()); } @@ -695,36 +687,36 @@ void createInstitutionAndPersistInstitutionId() { void sendCompletedEmail() { when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - doNothing().when(completionService).sendCompletedEmail(any()); + doNothing().when(completionService).sendCompletedEmail(any(), any()); function.sendMailCompletion(onboardingWorkflowString, executionContext); verify(completionService, times(1)) - .sendCompletedEmail(any()); + .sendCompletedEmail(any(), any()); } @Test void sendMailRejection() { when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - doNothing().when(completionService).sendMailRejection(any()); + doNothing().when(completionService).sendMailRejection(any(), any()); function.sendMailRejection(onboardinString, executionContext); verify(completionService, times(1)) - .sendMailRejection(any()); + .sendMailRejection(any(), any()); } @Test void sendCompletedEmailAggregate() { when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - doNothing().when(completionService).sendCompletedEmailAggregate(any()); + doNothing().when(completionService).sendCompletedEmailAggregate(any(), any()); function.sendMailCompletionAggregate(onboardinString, executionContext); verify(completionService, times(1)) - .sendCompletedEmailAggregate(any()); + .sendCompletedEmailAggregate(any(), any()); } diff --git a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/CompletionServiceDefaultTest.java b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/CompletionServiceDefaultTest.java index d946b2fe0..a5843d561 100644 --- a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/CompletionServiceDefaultTest.java +++ b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/CompletionServiceDefaultTest.java @@ -85,6 +85,14 @@ public class CompletionServiceDefaultTest { DelegationApi delegationApi; final String productId = "productId"; + private static final UserResource userResource; + + static { + userResource = new UserResource(); + userResource.setId(UUID.randomUUID()); + Map map = new HashMap<>(); + userResource.setWorkContacts(map); + } public static class UserMSProfile implements QuarkusTestProfile { @Override @@ -101,7 +109,7 @@ void createInstitutionAndPersistInstitutionId_shouldThrowExceptionIfMoreInstitut response.setInstitutions(List.of(new InstitutionResponse(), new InstitutionResponse())); when(institutionApi.getInstitutionsUsingGET(onboarding.getInstitution().getTaxCode(), onboarding.getInstitution().getSubunitCode(), null, null)) - .thenReturn(response); + .thenReturn(response); assertThrows(GenericOnboardingException.class, () -> completionServiceDefault.createInstitutionAndPersistInstitutionId(onboarding)); } @@ -120,6 +128,46 @@ void createInstitutionAndPersistInstitutionId_foundInstitution() { mockOnboardingUpdateAndExecuteCreateInstitution(onboarding); } + @Test + void createOrRetrieveInstitutionSuccess() { + Onboarding onboarding = createOnboarding(); + Institution institution = new Institution(); + institution.setId("actual-id"); + institution.setTaxCode("123"); + onboarding.setInstitution(institution); + + InstitutionsResponse response = new InstitutionsResponse(); + InstitutionResponse institutionResponse = new InstitutionResponse(); + institutionResponse.setId("actual-id"); + response.setInstitutions(List.of(institutionResponse)); + + when(institutionApi.getInstitutionsUsingGET(institution.getTaxCode(), null, null, null)) + .thenReturn(response); + + InstitutionResponse serviceResponse = completionServiceDefault.createOrRetrieveInstitution(onboarding); + + assertNotNull(serviceResponse); + assertEquals(serviceResponse.getId(), "actual-id"); + } + + @Test + void createOrRetrieveInstitutionFailure() { + Onboarding onboarding = createOnboarding(); + Institution institution = new Institution(); + institution.setId("actual-id"); + institution.setTaxCode("123"); + onboarding.setInstitution(institution); + + InstitutionsResponse response = new InstitutionsResponse(); + InstitutionResponse institutionResponse = new InstitutionResponse(); + response.setInstitutions(List.of(institutionResponse, institutionResponse)); + + when(institutionApi.getInstitutionsUsingGET(institution.getTaxCode(), null, null, null)) + .thenReturn(response); + + assertThrows(GenericOnboardingException.class, () -> completionServiceDefault.createOrRetrieveInstitution(onboarding)); + } + void mockOnboardingUpdateAndExecuteCreateInstitution(Onboarding onboarding){ PanacheUpdate panacheUpdateMock = mock(PanacheUpdate.class); when(panacheUpdateMock.where("_id", onboarding.getId())) @@ -133,6 +181,22 @@ void mockOnboardingUpdateAndExecuteCreateInstitution(Onboarding onboarding){ .update("institution.id = ?1 and updatedAt = ?2 ", any(), any()); } + @Test + void persistUpadatedAt(){ + Onboarding onboarding = createOnboarding(); + + PanacheUpdate panacheUpdateMock = mock(PanacheUpdate.class); + when(panacheUpdateMock.where("_id", onboarding.getId())) + .thenReturn(Long.valueOf(1)); + when(onboardingRepository.update("activatedAt.id = ?1 and updatedAt = ?2 ", any(), any())) + .thenReturn(panacheUpdateMock); + + completionServiceDefault.persistActivatedAt(onboarding); + + verify(onboardingRepository, times(1)) + .update("activatedAt = ?1 and updatedAt = ?2 ", any(), any()); + } + @Test void createInstitutionAndPersistInstitutionId_notFoundInstitutionAndCreateSaAnac() { Onboarding onboarding = createOnboarding(); @@ -416,18 +480,13 @@ void persistOnboarding() { @Test void sendCompletedEmail() { - UserResource userResource = new UserResource(); - userResource.setId(UUID.randomUUID()); - Map map = new HashMap<>(); - userResource.setWorkContacts(map); Product product = createDummyProduct(); Onboarding onboarding = createOnboarding(); OnboardingWorkflow onboardingWorkflow = new OnboardingWorkflowInstitution(onboarding, "INSTITUTION"); + User user = createDummyUser(onboarding); - User user = new User(); - user.setRole(PartyRole.MANAGER); - user.setId("user-id"); - onboarding.setUsers(List.of(user)); + ExecutionContext context = mock(ExecutionContext.class); + doReturn(Logger.getGlobal()).when(context).getLogger(); when(productService.getProduct(onboarding.getProductId())) .thenReturn(product); @@ -435,10 +494,35 @@ void sendCompletedEmail() { .thenReturn(userResource); doNothing().when(notificationService).sendCompletedEmail(any(), any(), any(), any(), any()); - completionServiceDefault.sendCompletedEmail(onboardingWorkflow); + completionServiceDefault.sendCompletedEmail(context, onboardingWorkflow); + + Mockito.verify(notificationService, times(1)) + .sendCompletedEmail(any(), any(), any(), any(), any()); + } + + @Test + void sendCompletedEmailWithError() { + + Product product = createDummyProduct(); + Onboarding onboarding = createOnboarding(); + OnboardingWorkflow onboardingWorkflow = new OnboardingWorkflowInstitution(onboarding, "INSTITUTION"); + + User user = createDummyUser(onboarding); + + ExecutionContext context = mock(ExecutionContext.class); + doReturn(Logger.getGlobal()).when(context).getLogger(); + when(productService.getProduct(onboarding.getProductId())) + .thenReturn(product); + when(userRegistryApi.findByIdUsingGET(USERS_FIELD_LIST, user.getId())) + .thenReturn(userResource); + GenericOnboardingException exception = new GenericOnboardingException("error"); + doThrow(exception).when(notificationService).sendCompletedEmail(any(), any(), any(), any(), any()); + + completionServiceDefault.sendCompletedEmail(context, onboardingWorkflow); Mockito.verify(notificationService, times(1)) .sendCompletedEmail(any(), any(), any(), any(), any()); + } @Test @@ -446,17 +530,15 @@ void sendMailRejection() { Product product = createDummyProduct(); Onboarding onboarding = createOnboarding(); + createDummyUser(onboarding); - User user = new User(); - user.setRole(PartyRole.MANAGER); - user.setId("user-id"); - onboarding.setUsers(List.of(user)); + ExecutionContext context = mock(ExecutionContext.class); + doReturn(Logger.getGlobal()).when(context).getLogger(); when(productService.getProduct(onboarding.getProductId())) .thenReturn(product); doNothing().when(notificationService).sendMailRejection(any(), any(), any()); - - completionServiceDefault.sendMailRejection(onboarding); + completionServiceDefault.sendMailRejection(context, onboarding); Mockito.verify(notificationService, times(1)) .sendMailRejection(any(), any(), any()); @@ -465,25 +547,21 @@ void sendMailRejection() { @Test void sendCompletedEmailAggregate() { - UserResource userResource = new UserResource(); - userResource.setId(UUID.randomUUID()); - Map map = new HashMap<>(); - userResource.setWorkContacts(map); Onboarding onboarding = createOnboarding(); Aggregator aggregator= new Aggregator(); aggregator.setDescription("description"); onboarding.setAggregator(aggregator); - User user = new User(); - user.setRole(PartyRole.MANAGER); - user.setId("user-id"); - onboarding.setUsers(List.of(user)); + User user = createDummyUser(onboarding); + + ExecutionContext context = mock(ExecutionContext.class); + doReturn(Logger.getGlobal()).when(context).getLogger(); when(userRegistryApi.findByIdUsingGET(USERS_FIELD_LIST, user.getId())) .thenReturn(userResource); doNothing().when(notificationService).sendCompletedEmailAggregate(any(), any()); - completionServiceDefault.sendCompletedEmailAggregate(onboarding); + completionServiceDefault.sendCompletedEmailAggregate(context, onboarding); Mockito.verify(notificationService, times(1)) .sendCompletedEmailAggregate(any(), any()); @@ -493,11 +571,7 @@ void sendCompletedEmailAggregate() { void persistUsers() { Onboarding onboarding = createOnboarding(); - - User user = new User(); - user.setRole(PartyRole.MANAGER); - user.setId("user-id"); - onboarding.setUsers(List.of(user)); + createDummyUser(onboarding); onboarding.setDelegationId("delegationId"); Response response = new ServerResponse(null, 200, null); @@ -511,13 +585,8 @@ void persistUsers() { @Test void persistUsersWithException() { - Onboarding onboarding = createOnboarding(); - - User user = new User(); - user.setRole(PartyRole.MANAGER); - user.setId("user-id"); - onboarding.setUsers(List.of(user)); + createDummyUser(onboarding); Response response = new ServerResponse(null, 500, null); when(userControllerApi.usersUserIdPost(any(), any(), any())).thenReturn(response); @@ -568,40 +637,6 @@ void createDelegationWithNullAggregator(){ Mockito.verifyNoInteractions(delegationApi); } - private InstitutionResponse dummyInstitutionResponse() { - InstitutionResponse response = new InstitutionResponse(); - response.setId("response-id"); - return response; - } - - - private Onboarding createOnboarding() { - Onboarding onboarding = new Onboarding(); - onboarding.setId(onboarding.getId()); - onboarding.setProductId(productId); - onboarding.setPricingPlan("pricingPlan"); - onboarding.setUsers(List.of()); - onboarding.setInstitution(new Institution()); - onboarding.setUserRequestUid("example-uid"); - - Billing billing = new Billing(); - billing.setPublicServices(true); - billing.setRecipientCode("example"); - billing.setVatNumber("example"); - billing.setTaxCodeInvoicing("taxCodeInvoicing"); - onboarding.setBilling(billing); - return onboarding; - } - - private Product createDummyProduct() { - Product product = new Product(); - product.setContractTemplatePath("example"); - product.setContractTemplateVersion("version"); - product.setTitle("Title"); - product.setId(productId); - return product; - } - @Test void testCreateAggregateOnboardingRequest() { // Given @@ -699,7 +734,7 @@ public static Onboarding createSampleOnboarding() { void sendTestEmail() { ExecutionContext executionContext = mock(ExecutionContext.class); when(executionContext.getLogger()).thenReturn(Logger.getGlobal()); - + doNothing().when(notificationService).sendTestEmail(executionContext); completionServiceDefault.sendTestEmail(executionContext); @@ -708,5 +743,47 @@ void sendTestEmail() { .sendTestEmail(executionContext); } + private User createDummyUser(Onboarding onboarding) { + User user = new User(); + user.setRole(PartyRole.MANAGER); + user.setId("user-id"); + onboarding.setUsers(List.of(user)); + return user; + } + + private InstitutionResponse dummyInstitutionResponse() { + InstitutionResponse response = new InstitutionResponse(); + response.setId("response-id"); + return response; + } + + + private Onboarding createOnboarding() { + Onboarding onboarding = new Onboarding(); + onboarding.setId(onboarding.getId()); + onboarding.setProductId(productId); + onboarding.setPricingPlan("pricingPlan"); + onboarding.setUsers(List.of()); + onboarding.setInstitution(new Institution()); + onboarding.setUserRequestUid("example-uid"); + + Billing billing = new Billing(); + billing.setPublicServices(true); + billing.setRecipientCode("example"); + billing.setVatNumber("example"); + billing.setTaxCodeInvoicing("taxCodeInvoicing"); + onboarding.setBilling(billing); + return onboarding; + } + + private Product createDummyProduct() { + Product product = new Product(); + product.setContractTemplatePath("example"); + product.setContractTemplateVersion("version"); + product.setTitle("Title"); + product.setId(productId); + return product; + } + } diff --git a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationEventResenderServiceDefaultTest.java b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationEventResenderServiceDefaultTest.java index 6d6dc13e4..c47bd402c 100644 --- a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationEventResenderServiceDefaultTest.java +++ b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationEventResenderServiceDefaultTest.java @@ -5,14 +5,14 @@ import io.quarkus.test.junit.QuarkusTest; import it.pagopa.selfcare.onboarding.dto.ResendNotificationsFilters; import it.pagopa.selfcare.onboarding.entity.Onboarding; -import it.pagopa.selfcare.onboarding.exception.NotificationException; import jakarta.inject.Inject; import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.List; import static it.pagopa.selfcare.onboarding.TestUtils.getMockedContext; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -28,48 +28,49 @@ class NotificationEventResenderServiceDefaultTest { OnboardingService onboardingService; @Test - void resendNotifications() { + void resendNotificationsEndsWithNullIfIsWorkingOnLastPage() { // Arrange ResendNotificationsFilters filters = ResendNotificationsFilters.builder().onboardingId("test").build(); ExecutionContext context = getMockedContext(); - Onboarding onboarding = new Onboarding(); - onboarding.setId("id1"); - Onboarding onboarding2 = new Onboarding(); - onboarding2.setId("id2"); - - when(onboardingService.getOnboardingsToResend(filters, 0, 100)).thenReturn(List.of(onboarding, onboarding2)); + when(onboardingService.getOnboardingsToResend(filters, 0, 100)).thenReturn(mockOnboardingList(2)); doNothing().when(notificationEventService).send(any(), any(), any()); // Act ResendNotificationsFilters resendNotificationsFilters = notificationEventResenderServiceDefault.resendNotifications(filters, context); // Assert - verify(notificationEventService, times(2)).send(any(), any(), any()); + verify(notificationEventService, times(2)).send(any(), any(), any(), any()); verify(onboardingService).getOnboardingsToResend(filters, 0, 100); assertNull(resendNotificationsFilters); } @Test - void resendNotificationsDoesntStopWhenSendProcessFails() { + void resendNotificationsEndsIncrementingPageIfIsWorkingOnIntermediatePage() { // Arrange - ResendNotificationsFilters filters = new ResendNotificationsFilters(); + ResendNotificationsFilters filters = ResendNotificationsFilters.builder().onboardingId("test").build(); ExecutionContext context = getMockedContext(); - Onboarding onboarding = new Onboarding(); - onboarding.setId("id1"); - Onboarding onboarding2 = new Onboarding(); - onboarding2.setId("id2"); - - doThrow(new NotificationException("Error")).when(notificationEventService).send(context, onboarding, null); - when(onboardingService.getOnboardingsToResend(filters, 0, 100)).thenReturn(List.of(onboarding, onboarding2)); + when(onboardingService.getOnboardingsToResend(filters, 0, 100)).thenReturn(mockOnboardingList(100)); + doNothing().when(notificationEventService).send(any(), any(), any()); // Act ResendNotificationsFilters resendNotificationsFilters = notificationEventResenderServiceDefault.resendNotifications(filters, context); // Assert - verify(notificationEventService, times(2)).send(any(), any(), any()); + verify(notificationEventService, times(100)).send(any(), any(), any(), any()); verify(onboardingService).getOnboardingsToResend(filters, 0, 100); - assertNull(resendNotificationsFilters); + assertNotNull(resendNotificationsFilters); + assertEquals(1, resendNotificationsFilters.getPage()); + } + + private List mockOnboardingList(int size) { + List onboardings = new ArrayList<>(); + for (int i = 0; i < size; i++) { + Onboarding onboarding = new Onboarding(); + onboarding.setId("id" + i); + onboardings.add(onboarding); + } + return onboardings; } } \ No newline at end of file diff --git a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationEventServiceDefaultTest.java b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationEventServiceDefaultTest.java index 57741694c..4e1dd424f 100644 --- a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationEventServiceDefaultTest.java +++ b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationEventServiceDefaultTest.java @@ -160,7 +160,7 @@ void sendMessageWithError() { .when(eventHubRestClient).sendMessage(anyString(), anyString()); ExecutionContext context = mock(ExecutionContext.class); doReturn(Logger.getGlobal()).when(context).getLogger(); - assertThrows(NotificationException.class, () -> messageServiceDefault.send(context, onboarding, QueueEvent.ADD)); + assertDoesNotThrow(() -> messageServiceDefault.send(context, onboarding, QueueEvent.ADD)); verify(eventHubRestClient, times(1)) .sendMessage(anyString(), anyString()); } @@ -214,8 +214,9 @@ void notificationEventMapTest() { billing.setPublicService(false); notificationToSend.setBilling(billing); - Map properties = NotificationEventServiceDefault.notificationEventMap(notificationToSend, "topic"); + Map properties = NotificationEventServiceDefault.notificationEventMap(notificationToSend, "topic", "traceId"); assertNotNull(properties); + assertEquals(properties.get("notificationEventTraceId"), "traceId"); assertEquals(properties.get("id"), "id"); assertEquals(properties.get("internalIstitutionID"), "internal"); assertEquals(properties.get("product"), "prod"); @@ -261,7 +262,7 @@ void notificationEventMapRootParentTest() { billing.setTaxCodeInvoicing("456"); notificationToSend.setBilling(billing); - Map properties = NotificationEventServiceDefault.notificationEventMap(notificationToSend, "topic"); + Map properties = NotificationEventServiceDefault.notificationEventMap(notificationToSend, "topic", null); assertNotNull(properties); assertEquals(properties.get("id"), "id"); assertEquals(properties.get("internalIstitutionID"), "internal"); diff --git a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationServiceDefaultTest.java b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationServiceDefaultTest.java index 9ee34b3db..f1afaedff 100644 --- a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationServiceDefaultTest.java +++ b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/NotificationServiceDefaultTest.java @@ -50,7 +50,7 @@ class NotificationServiceDefaultTest { void startup() { mailer = mock(Mailer.class); this.notificationService = new NotificationServiceDefault(templatePlaceholdersConfig, templatePathConfig, - azureBlobClient, objectMapper, mailer, contractService, notificationAdminMail, "senderMail", false, "destinationMailTestAddress"); + azureBlobClient, objectMapper, mailer, contractService, notificationAdminMail, "senderMail", false, "destinationMailTestAddress", true); } @Test diff --git a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceTest.java b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceTest.java index f2572df5c..6e9ecfaf5 100644 --- a/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceTest.java +++ b/apps/onboarding-functions/src/test/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceTest.java @@ -205,8 +205,7 @@ private Product createDummyProduct() { void saveToken_shouldSkipIfTokenExists() { OnboardingWorkflow onboardingWorkflow = new OnboardingWorkflowInstitution(); Onboarding onboarding = createOnboarding(); - Token token = new Token(); - token.setId(UUID.randomUUID().toString()); + Token token = createDummyToken(); onboardingWorkflow.setOnboarding(onboarding); when(tokenRepository.findByOnboardingId(onboarding.getId())) @@ -219,7 +218,6 @@ void saveToken_shouldSkipIfTokenExists() { Mockito.verifyNoMoreInteractions(tokenRepository); } - @Test void saveToken() { Onboarding onboarding = createOnboarding(); @@ -239,7 +237,6 @@ void saveToken() { onboardingService.saveTokenWithContract(onboardingWorkflow); - ArgumentCaptor tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class); Mockito.verify(tokenRepository, Mockito.times(1)) .persist(tokenArgumentCaptor.capture()); @@ -266,15 +263,13 @@ void loadContract() { .loadContractPDF(product.getContractTemplatePath(), onboarding.getId(), product.getTitle()); } - @Test void sendMailRegistrationWithContract() { Onboarding onboarding = createOnboarding(); Product product = createDummyProduct(); UserResource userResource = createUserResource(); - Token token = new Token(); - token.setId(UUID.randomUUID().toString()); + Token token = createDummyToken(); when(tokenRepository.findByOnboardingId(onboarding.getId())) .thenReturn(Optional.of(token)); @@ -297,7 +292,9 @@ void sendMailRegistrationWithContract() { sendMailInput, "default", "default"); - onboardingService.sendMailRegistrationForContract(onboardingWorkflow); + ExecutionContext context = getExecutionContext(); + + onboardingService.sendMailRegistrationForContract(context, onboardingWorkflow); Mockito.verify(notificationService, times(1)) .sendMailRegistrationForContract(any(), @@ -314,8 +311,7 @@ void sendMailRegistrationWithContractAggregator() { Onboarding onboarding = createOnboarding(); Product product = createDummyProduct(); UserResource userResource = createUserResource(); - Token token = new Token(); - token.setId(UUID.randomUUID().toString()); + Token token = createDummyToken(); when(tokenRepository.findByOnboardingId(onboarding.getId())) .thenReturn(Optional.of(token)); @@ -330,7 +326,9 @@ void sendMailRegistrationWithContractAggregator() { userResource.getName().getValue(), userResource.getFamilyName().getValue(), product.getTitle()); - onboardingService.sendMailRegistrationForContractAggregator(onboarding); + ExecutionContext context = getExecutionContext(); + + onboardingService.sendMailRegistrationForContractAggregator(context, onboarding); Mockito.verify(notificationService, times(1)) .sendMailRegistrationForContractAggregator(onboarding.getId(), @@ -339,14 +337,44 @@ void sendMailRegistrationWithContractAggregator() { product.getTitle()); } + @Test + void sendMailRegistrationWithContractAggregatorWithError() { + + Onboarding onboarding = createOnboarding(); + Product product = createDummyProduct(); + UserResource userResource = createUserResource(); + Token token = createDummyToken(); + + when(tokenRepository.findByOnboardingId(onboarding.getId())) + .thenReturn(Optional.of(token)); + when(productService.getProduct(onboarding.getProductId())) + .thenReturn(product); + + when(userRegistryApi.findByIdUsingGET(USERS_FIELD_LIST, onboarding.getUserRequestUid())) + .thenReturn(userResource); + + GenericOnboardingException exception = new GenericOnboardingException("errorCode"); + doThrow(exception).when(notificationService) + .sendMailRegistrationForContractAggregator(onboarding.getId(), + onboarding.getInstitution().getDigitalAddress(), + userResource.getName().getValue(), userResource.getFamilyName().getValue(), + product.getTitle()); + + ExecutionContext context = getExecutionContext(); + onboardingService.sendMailRegistrationForContractAggregator(context, onboarding); + Mockito.verify(notificationService, times(1)) + .sendMailRegistrationForContractAggregator(onboarding.getId(), + onboarding.getInstitution().getDigitalAddress(), + userResource.getName().getValue(), userResource.getFamilyName().getValue(), + product.getTitle()); + } @Test void sendMailRegistrationWithContractWhenApprove() { Onboarding onboarding = createOnboarding(); Product product = createDummyProduct(); - Token token = new Token(); - token.setId(UUID.randomUUID().toString()); + Token token = createDummyToken(); when(tokenRepository.findByOnboardingId(onboarding.getId())) .thenReturn(Optional.of(token)); @@ -362,7 +390,9 @@ void sendMailRegistrationWithContractWhenApprove() { product.getTitle(), "description", "default", "default"); - onboardingService.sendMailRegistrationForContractWhenApprove(onboardingWorkflow); + ExecutionContext context = getExecutionContext(); + + onboardingService.sendMailRegistrationForContractWhenApprove(context, onboardingWorkflow); Mockito.verify(notificationService, times(1)) .sendMailRegistrationForContract(onboarding.getId(), @@ -372,17 +402,16 @@ void sendMailRegistrationWithContractWhenApprove() { "default", "default"); } - @Test void sendMailRegistrationWithContract_throwExceptionWhenTokenIsNotPresent() { Onboarding onboarding = createOnboarding(); OnboardingWorkflow onboardingWorkflow = getOnboardingWorkflowInstitution(onboarding); when(tokenRepository.findByOnboardingId(onboarding.getId())) .thenReturn(Optional.empty()); - assertThrows(GenericOnboardingException.class, () -> onboardingService.sendMailRegistrationForContract(onboardingWorkflow)); + ExecutionContext context = getExecutionContext(); + assertThrows(GenericOnboardingException.class, () -> onboardingService.sendMailRegistrationForContract(context, onboardingWorkflow)); } - @Test void sendMailRegistration() { @@ -399,7 +428,9 @@ void sendMailRegistration() { userResource.getName().getValue(), userResource.getFamilyName().getValue(), product.getTitle()); - onboardingService.sendMailRegistration(onboarding); + ExecutionContext context = getExecutionContext(); + + onboardingService.sendMailRegistration(context, onboarding); Mockito.verify(notificationService, times(1)) .sendMailRegistration(onboarding.getInstitution().getDescription(), @@ -408,6 +439,33 @@ void sendMailRegistration() { product.getTitle()); } + @Test + void sendMailRegistrationWithError() { + + UserResource userResource = createUserResource(); + Product product = createDummyProduct(); + Onboarding onboarding = createOnboarding(); + + when(productService.getProduct(onboarding.getProductId())) + .thenReturn(product); + when(userRegistryApi.findByIdUsingGET(USERS_FIELD_LIST, onboarding.getUserRequestUid())) + .thenReturn(userResource); + GenericOnboardingException exception = new GenericOnboardingException("error"); + doThrow(exception).when(notificationService).sendMailRegistration(onboarding.getInstitution().getDescription(), + onboarding.getInstitution().getDigitalAddress(), + userResource.getName().getValue(), userResource.getFamilyName().getValue(), + product.getTitle()); + + ExecutionContext context = getExecutionContext(); + onboardingService.sendMailRegistration(context, onboarding); + + Mockito.verify(notificationService, times(1)) + .sendMailRegistration(onboarding.getInstitution().getDescription(), + onboarding.getInstitution().getDigitalAddress(), + userResource.getName().getValue(), userResource.getFamilyName().getValue(), + product.getTitle()); + } + @Test void sendMailRegistrationApprove() { @@ -423,7 +481,36 @@ void sendMailRegistrationApprove() { doNothing().when(notificationService) .sendMailRegistrationApprove(any(), any(), any(),any(),any()); - onboardingService.sendMailRegistrationApprove(onboarding); + ExecutionContext context = getExecutionContext(); + + onboardingService.sendMailRegistrationApprove(context, onboarding); + + Mockito.verify(notificationService, times(1)) + .sendMailRegistrationApprove(onboarding.getInstitution().getDescription(), + userResource.getName().getValue(), + userResource.getFamilyName().getValue(), + product.getTitle(), + onboarding.getId()); + } + + @Test + void sendMailRegistrationApproveWithError() { + + Onboarding onboarding = createOnboarding(); + Product product = createDummyProduct(); + UserResource userResource = createUserResource(); + + when(productService.getProduct(onboarding.getProductId())) + .thenReturn(product); + when(userRegistryApi.findByIdUsingGET(USERS_FIELD_LIST, onboarding.getUserRequestUid())) + .thenReturn(userResource); + GenericOnboardingException exception = new GenericOnboardingException("Something went wrong"); + doThrow(exception).when(notificationService) + .sendMailRegistrationApprove(any(), any(), any(),any(),any()); + + ExecutionContext context = getExecutionContext(); + + onboardingService.sendMailRegistrationApprove(context, onboarding); Mockito.verify(notificationService, times(1)) .sendMailRegistrationApprove(onboarding.getInstitution().getDescription(), @@ -439,7 +526,8 @@ void sendMailRegistrationApprove_throwExceptionWhenTokenIsNotPresent() { Onboarding onboarding = createOnboarding(); when(tokenRepository.findByOnboardingId(onboarding.getId())) .thenReturn(Optional.empty()); - assertThrows(GenericOnboardingException.class, () -> onboardingService.sendMailRegistrationApprove(onboarding)); + ExecutionContext context = getExecutionContext(); + assertThrows(GenericOnboardingException.class, () -> onboardingService.sendMailRegistrationApprove(context, onboarding)); } @@ -456,7 +544,9 @@ void sendMailOnboardingApprove() { .thenReturn(userResource); doNothing().when(notificationService).sendMailOnboardingApprove(any(), any(), any(),any(),any()); - onboardingService.sendMailOnboardingApprove(onboarding); + ExecutionContext context = getExecutionContext(); + + onboardingService.sendMailOnboardingApprove(context, onboarding); Mockito.verify(notificationService, times(1)) @@ -473,7 +563,8 @@ void sendMailOnboardingApprove_throwExceptionWhenTokenIsNotPresent() { Onboarding onboarding = createOnboarding(); when(tokenRepository.findByOnboardingId(onboarding.getId())) .thenReturn(Optional.empty()); - assertThrows(GenericOnboardingException.class, () -> onboardingService.sendMailOnboardingApprove(onboarding)); + ExecutionContext context = getExecutionContext(); + assertThrows(GenericOnboardingException.class, () -> onboardingService.sendMailOnboardingApprove(context, onboarding)); } @Test @@ -481,8 +572,7 @@ void countOnboardingShouldReturnCorrectResultsWhenProductsExist() { String from = "2021-01-01"; String to = "2021-12-31"; - ExecutionContext context = mock(ExecutionContext.class); - doReturn(Logger.getGlobal()).when(context).getLogger(); + ExecutionContext context = getExecutionContext(); PanacheQuery onboardingQuery = mock(PanacheQuery.class); @@ -502,8 +592,7 @@ void countOnboardingShouldReturnCorrectResultsWhenProductsExist() { @Test void countOnboardingShouldReturnEmptyListWhenNoProductsExist() { - ExecutionContext context = mock(ExecutionContext.class); - doReturn(Logger.getGlobal()).when(context).getLogger(); + ExecutionContext context = getExecutionContext(); when(productService.getProducts(true, false)).thenReturn(List.of()); List results = onboardingService.countNotifications(null, null, null, context); @@ -516,8 +605,7 @@ void getOnboardingsToResendShouldReturnResults() { filters.setFrom("2021-01-01"); filters.setTo("2021-12-31"); - ExecutionContext context = mock(ExecutionContext.class); - doReturn(Logger.getGlobal()).when(context).getLogger(); + getExecutionContext(); PanacheQuery onboardingQuery = mock(PanacheQuery.class); when(onboardingRepository.find(any())).thenReturn(onboardingQuery); @@ -534,8 +622,7 @@ void getOnboardingsToResendShouldReturnEmptyList() { filters.setFrom("2021-01-01"); filters.setTo("2021-12-31"); - ExecutionContext context = mock(ExecutionContext.class); - doReturn(Logger.getGlobal()).when(context).getLogger(); + getExecutionContext(); PanacheQuery onboardingQuery = mock(PanacheQuery.class); when(onboardingRepository.find(any())).thenReturn(onboardingQuery); @@ -545,4 +632,17 @@ void getOnboardingsToResendShouldReturnEmptyList() { List onboardings = onboardingService.getOnboardingsToResend(filters, 0, 100); assertTrue(onboardings.isEmpty()); } + + private ExecutionContext getExecutionContext() { + ExecutionContext context = mock(ExecutionContext.class); + doReturn(Logger.getGlobal()).when(context).getLogger(); + return context; + } + + private Token createDummyToken() { + Token token = new Token(); + token.setId(UUID.randomUUID().toString()); + return token; + } + } diff --git a/apps/onboarding-ms/src/main/docs/openapi.json b/apps/onboarding-ms/src/main/docs/openapi.json index 251c9dd03..e28a01fda 100644 --- a/apps/onboarding-ms/src/main/docs/openapi.json +++ b/apps/onboarding-ms/src/main/docs/openapi.json @@ -154,6 +154,12 @@ "schema" : { "type" : "string" } + }, { + "name" : "subunitCode", + "in" : "query", + "schema" : { + "type" : "string" + } }, { "name" : "taxCode", "in" : "query", @@ -1868,6 +1874,9 @@ "onboardingId" : { "type" : "string" }, + "subunitCode" : { + "type" : "string" + }, "taxCode" : { "type" : "string" }, diff --git a/apps/onboarding-ms/src/main/docs/openapi.yaml b/apps/onboarding-ms/src/main/docs/openapi.yaml index 1846ab47f..e2140ac76 100644 --- a/apps/onboarding-ms/src/main/docs/openapi.yaml +++ b/apps/onboarding-ms/src/main/docs/openapi.yaml @@ -109,6 +109,10 @@ paths: in: query schema: type: string + - name: subunitCode + in: query + schema: + type: string - name: taxCode in: query schema: @@ -1318,6 +1322,8 @@ components: type: string onboardingId: type: string + subunitCode: + type: string taxCode: type: string status: diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/OnboardingController.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/OnboardingController.java index 298993d10..2dda8019a 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/OnboardingController.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/OnboardingController.java @@ -245,6 +245,7 @@ public Uni getOnboardingWithFilter(@QueryParam(value = "p @QueryParam(value = "taxCode") String taxCode, @QueryParam(value = "institutionId") String institutionId, @QueryParam(value = "onboardingId") String onboardingId, + @QueryParam(value = "subunitCode") String subunitCode, @QueryParam(value = "from") String from, @QueryParam(value = "to") String to, @QueryParam(value = "status") String status, @@ -255,6 +256,7 @@ public Uni getOnboardingWithFilter(@QueryParam(value = "p .taxCode(taxCode) .institutionId(institutionId) .onboardingId(onboardingId) + .subunitCode(subunitCode) .from(from) .to(to) .status(status) diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/request/BillingPaRequest.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/request/BillingPaRequest.java index 61303bf5e..c3bf69a1c 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/request/BillingPaRequest.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/request/BillingPaRequest.java @@ -1,6 +1,5 @@ package it.pagopa.selfcare.onboarding.controller.request; -import jakarta.validation.constraints.NotEmpty; import lombok.Data; @Data diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/model/CsvAggregate.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/model/CsvAggregate.java index 12f734b72..cf24afa18 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/model/CsvAggregate.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/model/CsvAggregate.java @@ -11,11 +11,11 @@ public class CsvAggregate { @CsvBindByPosition(position = 1) private String description; @CsvBindByPosition(position = 2) - private String subunitCode; + private String vatNumber; @CsvBindByPosition(position = 3) private String subunitType; @CsvBindByPosition(position = 4) - private String geoTaxonomy; + private String subunitCode; @CsvBindByPosition(position = 5) private String address; @CsvBindByPosition(position = 6) diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/model/OnboardingGetFilters.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/model/OnboardingGetFilters.java index 6e3cc4f9f..d73c99ab7 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/model/OnboardingGetFilters.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/model/OnboardingGetFilters.java @@ -11,6 +11,7 @@ public class OnboardingGetFilters { private String productId; private String institutionId; private String onboardingId; + private String subunitCode; private String taxCode; private String status; private String from; diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/AggregatesServiceDefault.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/AggregatesServiceDefault.java index 292253031..e87b4932e 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/AggregatesServiceDefault.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/AggregatesServiceDefault.java @@ -62,6 +62,9 @@ public class AggregatesServiceDefault implements AggregatesService{ public static final String ERROR_DESCRIPTION = "La ragione sociale è obbligatoria"; public static final String ERROR_SUBUNIT_TYPE = "SubunitType non valido"; + public static final String ERROR_AOO_UO = "In caso di AOO/UO è necessario specificare la tipologia e il codice univoco IPA AOO/UO"; + public static final String ERROR_VATNUMBER = "La partita IVA è obbligatoria"; + @Override public Uni validateAggregatesCsv(File file){ AggregatesCsvResponse aggregatesCsvResponse = readItemsFromCsv(file); @@ -119,6 +122,11 @@ private Uni checkRequiredFields(CsvAggregate csvAggregate) { return Uni.createFrom().failure(new InvalidRequestException(ERROR_TAXCODE)); } else if (StringUtils.isEmpty(csvAggregate.getDescription())) { return Uni.createFrom().failure(new InvalidRequestException(ERROR_DESCRIPTION)); + } else if (StringUtils.isEmpty(csvAggregate.getVatNumber())) { + return Uni.createFrom().failure(new InvalidRequestException(ERROR_VATNUMBER)); + } else if ((StringUtils.isEmpty(csvAggregate.getSubunitType()) && StringUtils.isNotEmpty(csvAggregate.getSubunitCode())) + || (StringUtils.isNotEmpty(csvAggregate.getSubunitType()) && StringUtils.isEmpty(csvAggregate.getSubunitCode()))) { + return Uni.createFrom().failure(new InvalidRequestException(ERROR_AOO_UO)); } return Uni.createFrom().voidItem(); } @@ -137,8 +145,10 @@ public AggregatesCsvResponse readItemsFromCsv(File file) { String nextLine; while ((nextLine = bufferedReader.readLine()) != null) { - parseLine(nextLine, lineNumber, resultList, errors); - lineNumber++; + if(!nextLine.startsWith("(*")){ + parseLine(nextLine, lineNumber, resultList, errors); + lineNumber++; + } } return new AggregatesCsvResponse(resultList, errors); diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefault.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefault.java index e91a43728..db5f9db7f 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefault.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefault.java @@ -38,13 +38,11 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; import org.bson.Document; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.jboss.logging.Logger; -import org.jboss.resteasy.reactive.ClientWebApplicationException; import org.openapi.quarkus.core_json.api.InstitutionApi; import org.openapi.quarkus.core_json.api.OnboardingApi; import org.openapi.quarkus.core_json.model.InstitutionResponse; @@ -446,12 +444,12 @@ private Uni checkIfAlreadyOnboardingAndValidateAllowedMap(Institution i return validateAllowedMap(institution.getTaxCode(), institution.getSubunitCode(), productId) .flatMap(ignored -> { String origin = institution.getOrigin() != null ? institution.getOrigin().getValue() : null; - return onboardingApi.verifyOnboardingInfoByFiltersUsingHEAD(productId, null, institution.getTaxCode(), origin, institution.getOriginId(), institution.getSubunitCode()) - .onItem().failWith(() -> new ResourceConflictException(String.format(PRODUCT_ALREADY_ONBOARDED.getMessage(), productId, institution.getTaxCode()), PRODUCT_ALREADY_ONBOARDED.getCode())) - .onFailure(ClientWebApplicationException.class).recoverWithUni(ex -> ((WebApplicationException) ex).getResponse().getStatus() == 404 - ? Uni.createFrom().item(Response.noContent().build()) - : Uni.createFrom().failure(new RuntimeException(ex.getMessage()))) - .replaceWith(Boolean.TRUE); + return verifyOnboarding(institution.getTaxCode(), institution.getSubunitCode(), origin, institution.getOriginId(), OnboardingStatus.COMPLETED, productId) + .flatMap(onboardingResponses -> onboardingResponses.isEmpty() + ? Uni.createFrom().item(Boolean.TRUE) + : Uni.createFrom().failure(new ResourceConflictException( + String.format(PRODUCT_ALREADY_ONBOARDED.getMessage(), productId, institution.getTaxCode()), + PRODUCT_ALREADY_ONBOARDED.getCode()))); }); } diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/util/QueryUtils.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/util/QueryUtils.java index cacc15112..cccb27fd6 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/util/QueryUtils.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/util/QueryUtils.java @@ -83,6 +83,7 @@ public static Map createMapForOnboardingQueryParameter(Onboardin Map queryParameterMap = new HashMap<>(); Optional.ofNullable(filters.getProductId()).ifPresent(value -> queryParameterMap.put(PRODUCT, value)); Optional.ofNullable(filters.getTaxCode()).ifPresent(value -> queryParameterMap.put(INSTITUTION_TAX_CODE, value)); + Optional.ofNullable(filters.getSubunitCode()).ifPresent(value -> queryParameterMap.put(INSTITUTION_SUBUNIT_CODE, value)); Optional.ofNullable(filters.getStatus()).ifPresent(value -> queryParameterMap.put(STATUS, value)); Optional.ofNullable(filters.getFrom()).ifPresent(value -> queryParameterMap.put(FROM, value)); Optional.ofNullable(filters.getTo()).ifPresent(value -> queryParameterMap.put(TO, value)); diff --git a/apps/onboarding-ms/src/test/java/it/pagopa/selfcare/onboarding/controller/OnboardingControllerTest.java b/apps/onboarding-ms/src/test/java/it/pagopa/selfcare/onboarding/controller/OnboardingControllerTest.java index dc9c0f89f..22b47f0b3 100644 --- a/apps/onboarding-ms/src/test/java/it/pagopa/selfcare/onboarding/controller/OnboardingControllerTest.java +++ b/apps/onboarding-ms/src/test/java/it/pagopa/selfcare/onboarding/controller/OnboardingControllerTest.java @@ -392,6 +392,7 @@ void getOnboarding() { OnboardingGetFilters filters = OnboardingGetFilters.builder() .productId("prod-io") .taxCode("taxCode") + .subunitCode("subunitCode") .from("2023-12-01") .to("2023-12-31") .status("ACTIVE") diff --git a/apps/onboarding-ms/src/test/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefaultTest.java b/apps/onboarding-ms/src/test/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefaultTest.java index 33a1eade0..74af8551a 100644 --- a/apps/onboarding-ms/src/test/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefaultTest.java +++ b/apps/onboarding-ms/src/test/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefaultTest.java @@ -228,14 +228,7 @@ void onboardingPa_throwExceptionIfProductAlreadyOnboarded(UniAsserter asserter) mockSimpleProductValidAssert(onboardingRequest.getProductId(), false, asserter); mockVerifyAllowedMap(onboardingRequest.getInstitution().getTaxCode(), onboardingRequest.getProductId(), asserter); - - asserter.execute(() -> when(onboardingApi.verifyOnboardingInfoByFiltersUsingHEAD(onboardingRequest.getProductId(), - null, - institutionBaseRequest.getTaxCode(), - null, - null, - institutionBaseRequest.getSubunitCode()) - ).thenReturn(Uni.createFrom().item(Response.noContent().build()))); + mockVerifyOnboardingNotEmpty(asserter); asserter.assertFailedWith(() -> onboardingService.onboarding(onboardingRequest, users), ResourceConflictException.class); } @@ -255,7 +248,7 @@ void onboarding_throwExceptionIfProductIsNotDelegable(UniAsserter asserter) { asserter.execute(() -> when(productService.getProductIsValid(onboardingRequest.getProductId())) .thenReturn(productResource)); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); asserter.assertFailedWith(() -> onboardingService.onboarding(onboardingRequest, users), OnboardingNotAllowedException.class); } @@ -275,7 +268,7 @@ void onboarding_throwExceptionIfProductRoleIsNotValid(UniAsserter asserter) { asserter.execute(() -> when(productService.getProductIsValid(onboardingRequest.getProductId())) .thenReturn(productResource)); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockPersistOnboarding(asserter); asserter.execute(() -> when(userRegistryApi.searchUsingPOST(any(), any())) @@ -300,7 +293,7 @@ void onboardingPa_throwExceptionIfProductParentRoleIsNotValid(UniAsserter assert asserter.execute(() -> when(productService.getProductIsValid(onboardingRequest.getProductId())) .thenReturn(productResource)); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockPersistOnboarding(asserter); asserter.execute(() -> when(userRegistryApi.searchUsingPOST(any(), any())) @@ -323,7 +316,7 @@ void onboarding_shouldThrowExceptionIfRoleNotValid(UniAsserter asserter) { .build()); mockSimpleProductValidAssert(onboardingDefaultRequest.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockPersistOnboarding(asserter); mockVerifyAllowedMap(onboardingDefaultRequest.getInstitution().getTaxCode(), onboardingDefaultRequest.getProductId(), asserter); @@ -354,7 +347,7 @@ void onboarding_Onboarding_addParentDescriptionForAooOrUo_Aoo(UniAsserter assert mockSimpleSearchPOSTAndPersist(asserter); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); AOOResource aooResource = new AOOResource(); aooResource.setDenominazioneEnte("TEST"); @@ -366,6 +359,7 @@ void onboarding_Onboarding_addParentDescriptionForAooOrUo_Aoo(UniAsserter assert asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -384,7 +378,7 @@ void onboarding_Onboarding_addParentDescriptionForAooOrUo_AooNotFound(UniAsserte request.setInstitution(institutionBaseRequest); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); AOOResource aooResource = new AOOResource(); @@ -413,7 +407,7 @@ void onboarding_Onboarding_addParentDescriptionForAooOrUo_AooException(UniAssert request.setInstitution(institutionBaseRequest); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); AOOResource aooResource = new AOOResource(); @@ -448,7 +442,7 @@ void onboarding_Onboarding_addParentDescriptionForAooOrUo_Uo(UniAsserter asserte mockSimpleSearchPOSTAndPersist(asserter); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); UOResource uoResource = new UOResource(); @@ -461,6 +455,7 @@ void onboarding_Onboarding_addParentDescriptionForAooOrUo_Uo(UniAsserter asserte asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -479,7 +474,7 @@ void onboarding_Onboarding_addParentDescriptionForAooOrUo_UoNotFound(UniAsserter request.setInstitution(institutionBaseRequest); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); ResourceNotFoundException resourceNotFoundException = new ResourceNotFoundException("Resource not found"); @@ -510,7 +505,7 @@ void onboarding_Onboarding_addParentDescriptionForAooOrUo_UoException(UniAsserte request.setInstitution(institutionBaseRequest); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); WebApplicationException exception = mock(WebApplicationException.class); @@ -572,7 +567,7 @@ void onboarding_Onboarding_Aggregator(UniAsserter asserter) { mockSimpleSearchPOSTAndPersist(asserter); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); asserter.assertThat(() -> onboardingService.onboarding(request, users), Assertions::assertNotNull); @@ -580,6 +575,7 @@ void onboarding_Onboarding_Aggregator(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -597,7 +593,7 @@ void onboardingSa_whenUserFoundedAndWillNotUpdate(UniAsserter asserter) { mockPersistOnboarding(asserter); mockSimpleSearchPOSTAndPersist(asserter); mockSimpleProductValidAssert(onboardingRequest.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(onboardingRequest.getInstitution().getTaxCode(), onboardingRequest.getProductId(), asserter); asserter.assertThat(() -> onboardingService.onboarding(onboardingRequest, users), Assertions::assertNotNull); @@ -605,6 +601,7 @@ void onboardingSa_whenUserFoundedAndWillNotUpdate(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -656,7 +653,7 @@ void onboardingPsp_whenUserFoundedAndWillNotUpdate(UniAsserter asserter) { mockPersistOnboarding(asserter); mockSimpleSearchPOSTAndPersist(asserter); mockSimpleProductValidAssert(onboardingRequest.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(onboardingRequest.getInstitution().getTaxCode(), onboardingRequest.getProductId(), asserter); asserter.assertThat(() -> onboardingService.onboarding(onboardingRequest, users), Assertions::assertNotNull); @@ -664,6 +661,7 @@ void onboardingPsp_whenUserFoundedAndWillNotUpdate(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -687,16 +685,13 @@ void onboardingPsp_whenUserFoundedAndWillNotUpdateAndProductHasParent(UniAsserte // mock parent has already onboarding - asserter.execute(() -> when(onboardingApi.verifyOnboardingInfoByFiltersUsingHEAD(product.getId(), null, institutionPspRequest.getTaxCode(), null, null, null)) - .thenReturn(Uni.createFrom().failure(new ClientWebApplicationException(404)))); - asserter.execute(() -> when(onboardingApi.verifyOnboardingInfoByFiltersUsingHEAD("productId", null, institutionPspRequest.getTaxCode(), null, null, null)) - .thenReturn(Uni.createFrom().failure(new ResourceConflictException("", "")))); - + mockVerifyOnboardingNotFound(); asserter.assertThat(() -> onboardingService.onboarding(onboardingRequest, users), Assertions::assertNotNull); asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -713,7 +708,7 @@ void onboarding_whenUserFoundedAndWillNotUpdate(UniAsserter asserter) { mockPersistOnboarding(asserter); mockSimpleSearchPOSTAndPersist(asserter); mockSimpleProductValidAssert(onboardingDefaultRequest.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(onboardingDefaultRequest.getInstitution().getTaxCode(), onboardingDefaultRequest.getProductId(), asserter); asserter.assertThat(() -> onboardingService.onboarding(onboardingDefaultRequest, users), Assertions::assertNotNull); @@ -721,6 +716,7 @@ void onboarding_whenUserFoundedAndWillNotUpdate(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -736,7 +732,7 @@ void onboarding_whenUserFoundedAndWillUpdate(UniAsserter asserter) { request.setInstitution(institutionPspRequest); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); asserter.execute(() -> PanacheMock.mock(Onboarding.class)); @@ -760,6 +756,7 @@ void onboarding_whenUserFoundedAndWillUpdate(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -781,7 +778,7 @@ void onboarding_whenUserFoundAndWillNotUpdate(UniAsserter asserter) { request.setInstitution(institutionPspRequest); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); asserter.execute(() -> PanacheMock.mock(Onboarding.class)); @@ -798,6 +795,7 @@ void onboarding_whenUserFoundAndWillNotUpdate(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -821,7 +819,7 @@ void onboarding_whenUserFoundedAndWillUpdateMailUuid(UniAsserter asserter) { request.setInstitution(institutionPspRequest); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); asserter.execute(() -> PanacheMock.mock(Onboarding.class)); @@ -845,6 +843,7 @@ void onboarding_whenUserFoundedAndWillUpdateMailUuid(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -869,7 +868,7 @@ void onboarding_whenUserNotFoundedAndWillSave(UniAsserter asserter) { .thenReturn(Uni.createFrom().item(UserId.builder().id(createUserId).build()))); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); asserter.execute(() -> when(Onboarding.persistOrUpdate(any(List.class))) @@ -884,6 +883,7 @@ void onboarding_whenUserNotFoundedAndWillSave(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -900,7 +900,7 @@ void onboarding_shouldThrowExceptionIfUserRegistryFails(UniAsserter asserter) { mockPersistOnboarding(asserter); mockSimpleProductValidAssert(onboardingDefaultRequest.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(onboardingDefaultRequest.getInstitution().getTaxCode(), onboardingDefaultRequest.getProductId(), asserter); asserter.execute(() -> when(userRegistryApi.searchUsingPOST(any(), any())) @@ -909,9 +909,21 @@ void onboarding_shouldThrowExceptionIfUserRegistryFails(UniAsserter asserter) { asserter.assertFailedWith(() -> onboardingService.onboarding(onboardingDefaultRequest, users), WebApplicationException.class); } - void mockVerifyOnboardingNotFound(UniAsserter asserter) { - asserter.execute(() -> when(onboardingApi.verifyOnboardingInfoByFiltersUsingHEAD(any(), any(), any(), any(), any(), any())) - .thenReturn(Uni.createFrom().failure(new ClientWebApplicationException(404)))); + void mockVerifyOnboardingNotFound() { + PanacheMock.mock(Onboarding.class); + ReactivePanacheQuery query = Mockito.mock(ReactivePanacheQuery.class); + when(query.stream()).thenReturn(Multi.createFrom().empty()); + when(Onboarding.find(any())).thenReturn(query); + } + + void mockVerifyOnboardingNotEmpty(UniAsserter asserter) { + + asserter.execute(() -> { + PanacheMock.mock(Onboarding.class); + ReactivePanacheQuery query = Mockito.mock(ReactivePanacheQuery.class); + when(query.stream()).thenReturn(Multi.createFrom().items(createDummyOnboarding())); + when(Onboarding.find(any())).thenReturn(query);}); + } @Test @@ -938,7 +950,7 @@ void completeWithoutSignatureVerification(UniAsserter asserter) { mockFindToken(asserter, onboarding.getId()); mockSimpleProductValidAssert(onboarding.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(onboarding.getInstitution().getTaxCode(), onboarding.getProductId(), asserter); final String filepath = "upload-file-path"; @@ -973,7 +985,7 @@ void completeWithoutSignatureValidation(UniAsserter asserter) { .verifySignature(any(), any(), any())); mockSimpleProductValidAssert(onboarding.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(onboarding.getInstitution().getTaxCode(), onboarding.getProductId(), asserter); final String filepath = "upload-file-path"; @@ -1009,7 +1021,7 @@ void completeOnboardingUsersWithoutSignatureValidation(UniAsserter asserter) { mockVerifyAllowedMap(onboarding.getInstitution().getTaxCode(), onboarding.getProductId(), asserter); mockSimpleProductValidAssert(onboarding.getProductId(), true, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); final String filepath = "upload-file-path"; when(azureBlobClient.uploadFile(any(), any(), any())).thenReturn(filepath); @@ -1093,6 +1105,30 @@ void testOnboardingGet() { subscriber.assertCompleted().assertItem(getResponse); } + @Test + void testOnboardingGet2() { + int page = 0, size = 3; + Onboarding onboarding = createDummyOnboarding(); + mockFindOnboarding(onboarding); + OnboardingGetResponse getResponse = getOnboardingGetResponse(onboarding); + OnboardingGetFilters filters = OnboardingGetFilters.builder() + .productId("prod-io") + .taxCode("taxCode") + .subunitCode("subunitCode") + .from("2023-12-01") + .to("2023-12-31") + .status("ACTIVE") + .page(page) + .size(size) + .build(); + UniAssertSubscriber subscriber = onboardingService + .onboardingGet(filters) + .subscribe() + .withSubscriber(UniAssertSubscriber.create()); + + subscriber.assertCompleted().assertItem(getResponse); + } + private OnboardingGetResponse getOnboardingGetResponse(Onboarding onboarding) { OnboardingGet onboardingGet = onboardingMapper.toGetResponse(onboarding); OnboardingGetResponse response = new OnboardingGetResponse(); @@ -1322,14 +1358,7 @@ void approve() { when(productService.getProductIsValid(onboarding.getProductId())) .thenReturn(createDummyProduct(onboarding.getProductId(), false)); - when(onboardingApi.verifyOnboardingInfoByFiltersUsingHEAD( - onboarding.getProductId(), - null, - onboarding.getInstitution().getTaxCode(), - null, - null, - onboarding.getInstitution().getSubunitCode()) - ).thenReturn(Uni.createFrom().failure(new ClientWebApplicationException(404))); + mockVerifyOnboardingNotFound(); when(orchestrationApi.apiStartOnboardingOrchestrationGet(onboarding.getId(), null)) .thenReturn(Uni.createFrom().item(new OrchestrationResponse())); @@ -1375,14 +1404,7 @@ void approveCompletion() { when(productService.getProductIsValid(onboarding.getProductId())) .thenReturn(createDummyProduct(onboarding.getProductId(), false)); - when(onboardingApi.verifyOnboardingInfoByFiltersUsingHEAD( - onboarding.getProductId(), - null, - onboarding.getInstitution().getTaxCode(), - null, - null, - onboarding.getInstitution().getSubunitCode()) - ).thenReturn(Uni.createFrom().failure(new ClientWebApplicationException(404))); + mockVerifyOnboardingNotFound(); when(onboardingValidationStrategy.validate(onboarding.getProductId(), onboarding.getInstitution().getTaxCode())) .thenReturn(true); @@ -1420,7 +1442,7 @@ void onboarding_Onboarding_importPA(UniAsserter asserter) { mockSimpleSearchPOSTAndPersist(asserter); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); asserter.execute(() -> when(userRegistryApi.updateUsingPATCH(any(), any())) @@ -1436,6 +1458,7 @@ void onboarding_Onboarding_importPA(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -1455,7 +1478,7 @@ void onboarding_aggregationCompletion(UniAsserter asserter) { mockSimpleSearchPOSTAndPersist(asserter); mockSimpleProductValidAssert(request.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(request.getInstitution().getTaxCode(), request.getProductId(), asserter); asserter.execute(() -> when(userRegistryApi.updateUsingPATCH(any(), any())) @@ -1471,6 +1494,7 @@ void onboarding_aggregationCompletion(UniAsserter asserter) { asserter.execute(() -> { PanacheMock.verify(Onboarding.class).persist(any(Onboarding.class), any()); PanacheMock.verify(Onboarding.class).persistOrUpdate(any(List.class)); + PanacheMock.verify(Onboarding.class).find(any(Document.class)); PanacheMock.verifyNoMoreInteractions(Onboarding.class); }); } @@ -1737,7 +1761,7 @@ void completeOnboardingUsers(UniAsserter asserter) { mockVerifyAllowedMap(onboarding.getInstitution().getTaxCode(), onboarding.getProductId(), asserter); mockSimpleProductValidAssert(onboarding.getProductId(), true, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); final String filepath = "upload-file-path"; when(azureBlobClient.uploadFile(any(), any(), any())).thenReturn(filepath); @@ -1770,7 +1794,7 @@ void complete(UniAsserter asserter) { .verifySignature(any(), any(), any())); mockSimpleProductValidAssert(onboarding.getProductId(), false, asserter); - mockVerifyOnboardingNotFound(asserter); + mockVerifyOnboardingNotFound(); mockVerifyAllowedMap(onboarding.getInstitution().getTaxCode(), onboarding.getProductId(), asserter); final String filepath = "upload-file-path"; diff --git a/apps/onboarding-ms/src/test/resources/aggregates.csv b/apps/onboarding-ms/src/test/resources/aggregates.csv index 617bdb5fb..9cf6bece3 100644 --- a/apps/onboarding-ms/src/test/resources/aggregates.csv +++ b/apps/onboarding-ms/src/test/resources/aggregates.csv @@ -1,10 +1,10 @@ codice fiscale,Ragione Sociale,subunitCode,subunitType,Area Geografica,Sede,Codice IPA -1437190414;Servizi turistici e culturali;AQ66UML;AOO;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA -00297110389;SAN LEO 2000 SERVIZI TURISTICI SRL;;;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA -4551120274;Progetto Tiburtina;KNDJE4;UO;;Via Torino 186;00L7M4KW -4551120275;;;;;Via Torino 186;00L7M4KW -;Servizi turistici e culturali;AQ66UML;AOO;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA +1437190414;Servizi turistici e culturali;123456456;AQ66UML;AOO;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA +00297110389;SAN LEO 2000 SERVIZI TURISTICI SRL;123456456;;;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA +4551120274;Progetto Tiburtina;123456456;KNDJE4;UO;;Via Torino 186;00L7M4KW +4551120275;;;;;;Via Torino 186;00L7M4KW +;Servizi turistici e culturali;123456456;AQ66UML;AOO;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA 4551120275;Servizi turistici e culturali;AQ66;AOO;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA 4551120275;Servizi turistici e culturali;AQ66;UO;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA -345645;Servizi turistici e culturali;;;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA -345645;Servizi turistici e culturali;123;AEO;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA +345645;Servizi turistici e culturali;123456456;;UO;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA +345645;Servizi turistici e culturali;123456456;123;;;PIAZZA DANTE ALIGHIERI 14;02IKT4NA diff --git a/infra/functions/onboarding-functions/env/uat-pnpg/terraform.tfvars b/infra/functions/onboarding-functions/env/uat-pnpg/terraform.tfvars index cb0436aec..9d7a9ef3c 100644 --- a/infra/functions/onboarding-functions/env/uat-pnpg/terraform.tfvars +++ b/infra/functions/onboarding-functions/env/uat-pnpg/terraform.tfvars @@ -68,13 +68,13 @@ app_settings = { "BACKOFF_COEFFICIENT" = "1" "EVENT_HUB_BASE_PATH" = "https://selc-u-eventhub-ns.servicebus.windows.net", "STANDARD_SHARED_ACCESS_KEY_NAME" = "selfcare-wo" - "EVENTHUB-SC-CONTRACTS-SELFCARE-WO-KEY-LC" = "string" + "EVENTHUB_SC_CONTRACTS_SELFCARE_WO_KEY_LC" = "string" "STANDARD_TOPIC_NAME" = "SC-Contracts" "SAP_SHARED_ACCESS_KEY_NAME" = "external-interceptor-wo" - "EVENTHUB-SC-CONTRACTS-SAP-SELFCARE-WO-KEY-LC" = "string" + "EVENTHUB_SC_CONTRACTS_SAP_SELFCARE_WO_KEY_LC" = "string" "SAP_TOPIC_NAME" = "SC-Contracts-SAP" "FD_SHARED_ACCESS_KEY_NAME" = "external-interceptor-wo" - "EVENTHUB-SC-CONTRACTS-FD-SELFCARE-WO-KEY-LC" = "string" + "EVENTHUB_SC_CONTRACTS_FD_SELFCARE_WO_KEY_LC" = "string" "FD_TOPIC_NAME" = "Selfcare-FD" "SAP_ALLOWED_INSTITUTION_TYPE" = "PA,GSP,SA,AS,SCP" "SAP_ALLOWED_ORIGINS" = "IPA,SELC"