Skip to content

Commit

Permalink
[SELC-5324] feat: added control to send two types of notifications (#424
Browse files Browse the repository at this point in the history
)
  • Loading branch information
empassaro authored Sep 19, 2024
1 parent e927e71 commit e15e95c
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,26 +1,50 @@
package it.pagopa.selfcare.onboarding.service;

import com.microsoft.applicationinsights.TelemetryClient;
import com.microsoft.applicationinsights.TelemetryConfiguration;
import com.microsoft.azure.functions.ExecutionContext;
import io.quarkus.runtime.util.ExceptionUtil;
import it.pagopa.selfcare.onboarding.common.OnboardingStatus;
import it.pagopa.selfcare.onboarding.dto.QueueEvent;
import it.pagopa.selfcare.onboarding.dto.ResendNotificationsFilters;
import it.pagopa.selfcare.onboarding.entity.Onboarding;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.Context;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static it.pagopa.selfcare.onboarding.utils.CustomMetricsConst.EVENT_ONBOARDING_FN_NAME;
import static it.pagopa.selfcare.onboarding.utils.CustomMetricsConst.EVENT_ONBOARDING_INSTTITUTION_FN_FAILURE;

@ApplicationScoped
public class NotificationEventResenderServiceDefault implements NotificationEventResenderService {
private final NotificationEventService notificationEventService;
private final OnboardingService onboardingService;

private final TelemetryClient telemetryClient;
public static final String OPERATION_NAME = "ONBOARDING-FN";
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) {
public NotificationEventResenderServiceDefault(
NotificationEventService notificationEventService,
OnboardingService onboardingService,
@Context @ConfigProperty(name = "onboarding-functions.appinsights.connection-string") String appInsightsConnectionString
) {
this.notificationEventService = notificationEventService;
this.onboardingService = onboardingService;
TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.createDefault();
telemetryConfiguration.setConnectionString(appInsightsConnectionString);
this.telemetryClient = new TelemetryClient(telemetryConfiguration);
this.telemetryClient.getContext().getOperation().setName(OPERATION_NAME);
}

public ResendNotificationsFilters resendNotifications(ResendNotificationsFilters filters, ExecutionContext context) {
Expand All @@ -33,9 +57,17 @@ public ResendNotificationsFilters resendNotifications(ResendNotificationsFilters
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, filters.getNotificationEventTraceId());
if(onboardingHasBeenDeletedInRange(onboarding, filters.getFrom(), filters.getTo())) {
notificationEventService.send(context, onboarding, QueueEvent.UPDATE, filters.getNotificationEventTraceId());
}

if(onboardingHasBeenActivatedInRange(onboarding, filters.getFrom(), filters.getTo())) {
onboarding.setStatus(OnboardingStatus.COMPLETED);
notificationEventService.send(context, onboarding, QueueEvent.ADD, filters.getNotificationEventTraceId());
}
} catch (Exception e) {
context.getLogger().severe(() -> String.format("ERROR: Sending onboarding %s error: %s ", onboarding.getId(), ExceptionUtil.generateStackTrace(e)));
trackErrorEvent(onboarding, e, filters.getNotificationEventTraceId());
}
}

Expand All @@ -49,4 +81,39 @@ public ResendNotificationsFilters resendNotifications(ResendNotificationsFilters
filters.setPage(page + 1);
return filters;
}

private boolean onboardingHasBeenDeletedInRange(Onboarding onboarding, String from, String to) {
if(onboarding.getStatus() != OnboardingStatus.DELETED) {
return false;
}

return doesDateFallInRange(onboarding.getDeletedAt(), from, to);
}

private boolean onboardingHasBeenActivatedInRange(Onboarding onboarding, String from, String to) {
return doesDateFallInRange(onboarding.getActivatedAt(), from, to);
}

private static boolean doesDateFallInRange(LocalDateTime date, String from, String to) {
if(date == null) {
return false;
}

LocalDate fromDate = StringUtils.isNotBlank(from) ? LocalDate.parse(from, DateTimeFormatter.ISO_LOCAL_DATE) : null;
LocalDate toDate = StringUtils.isNotBlank(to) ? LocalDate.parse(to, DateTimeFormatter.ISO_LOCAL_DATE) : null;
return (fromDate == null || date.isEqual(fromDate.atStartOfDay()) || date.isAfter(fromDate.atStartOfDay())) &&
(toDate == null || date.isEqual(toDate.atStartOfDay()) || date.isBefore(toDate.plusDays(1).atStartOfDay()));
}

private void trackErrorEvent(Onboarding onboarding, Exception e, String notificationEventTraceId) {
telemetryClient.trackEvent(EVENT_ONBOARDING_FN_NAME, onboardingEventFailureMap(onboarding, e, notificationEventTraceId), Map.of(EVENT_ONBOARDING_INSTTITUTION_FN_FAILURE, 1D));
}

private static Map<String, String> onboardingEventFailureMap(Onboarding onboarding, Exception e, String notificationEventTraceId) {
Map<String, String> propertiesMap = new HashMap<>();
Optional.ofNullable(onboarding.getId()).ifPresent(value -> propertiesMap.put("id", value));
Optional.ofNullable(notificationEventTraceId).ifPresent(value -> propertiesMap.put("notificationEventTraceId", value));
Optional.ofNullable(e).ifPresent(value -> propertiesMap.put("error", ExceptionUtil.generateStackTrace(e)));
return propertiesMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,12 @@

import java.util.*;

import static it.pagopa.selfcare.onboarding.utils.CustomMetricsConst.EVENT_ONBOARDING_FN_NAME;
import static it.pagopa.selfcare.onboarding.utils.CustomMetricsConst.EVENT_ONBOARDING_INSTTITUTION_FN_SUCCESS;
import static it.pagopa.selfcare.onboarding.utils.Utils.isNotInstitutionOnboarding;

@ApplicationScoped
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_SUCCESS = "EventsOnboardingInstitution_success";
public static final String OPERATION_NAME = "ONBOARDING-FN";
private final TelemetryClient telemetryClient;
@RestClient
@Inject
Expand Down Expand Up @@ -70,7 +67,7 @@ public NotificationEventServiceDefault(ProductService productService,
TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.createDefault();
telemetryConfiguration.setConnectionString(appInsightsConnectionString);
this.telemetryClient = new TelemetryClient(telemetryConfiguration);
this.telemetryClient.getContext().getOperation().setName(OPERATION_NAME);
this.telemetryClient.getContext().getOperation().setName(EVENT_ONBOARDING_FN_NAME);
mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
import java.util.Optional;
import java.util.stream.Collectors;

import static it.pagopa.selfcare.onboarding.utils.Utils.CONTRACT_FILENAME_FUNC;
import static it.pagopa.selfcare.onboarding.utils.Utils.*;
import java.util.stream.Stream;
import static it.pagopa.selfcare.onboarding.utils.Utils.NOT_ALLOWED_WORKFLOWS_FOR_INSTITUTION_NOTIFICATIONS;

@ApplicationScoped
Expand All @@ -52,7 +53,6 @@ public class OnboardingService {
public static final String USER_REQUEST_DOES_NOT_FOUND = "User request does not found for onboarding %s";
public static final String ACTIVATED_AT_FIELD = "activatedAt";
public static final String DELETED_AT_FIELD = "deletedAt";
public static final String CREATED_AT = "createdAt";
private static final String WORKFLOW_TYPE = "workflowType";

@RestClient
Expand Down Expand Up @@ -259,7 +259,8 @@ public List<NotificationCountResult> countNotifications(String productId, String
}


public NotificationCountResult countNotificationsByFilters(String productId, String from, String to, ExecutionContext context) {Document queryAddEvent = getQueryNotificationAdd(productId, from, to);
public NotificationCountResult countNotificationsByFilters(String productId, String from, String to, ExecutionContext context) {
Document queryAddEvent = getQueryNotificationAdd(productId, from, to);
Document queryUpdateEvent = getQueryNotificationDelete(productId, from, to);

long countAddEvents = repository.find(queryAddEvent).count();
Expand Down Expand Up @@ -289,7 +290,7 @@ private Document createQuery(String productId, List<OnboardingStatus> status, St
}
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))));
Optional.ofNullable(to).ifPresent(value -> query.append(dateField, dateQuery.append("$lte", LocalDate.parse(to, DateTimeFormatter.ISO_LOCAL_DATE).plusDays(1))));
if(!dateQuery.isEmpty()) {
query.append(dateField, dateQuery);
}
Expand Down Expand Up @@ -317,20 +318,38 @@ private Document createQueryByFilters(ResendNotificationsFilters filters) {
Optional.ofNullable(filters.getTaxCode()).ifPresent(value -> query.append("institution.taxCode", value));
query.append("status", new Document("$in", filters.getStatus()));

Document dateQuery = new Document();
Optional.ofNullable(filters.getFrom()).ifPresent(value -> query.append(CREATED_AT, dateQuery.append("$gte", LocalDate.parse(filters.getFrom(), DateTimeFormatter.ISO_LOCAL_DATE))));
Optional.ofNullable(filters.getTo()).ifPresent(value -> query.append(CREATED_AT, dateQuery.append("$lte", LocalDate.parse(filters.getTo(), DateTimeFormatter.ISO_LOCAL_DATE))));
if(!dateQuery.isEmpty()) {
query.append(CREATED_AT, dateQuery);
}
List<Document> dateQueries = createDateQueries(filters);
List<Document> workflowCriteria = createWorkflowCriteria();

query.append("$and", List.of(
new Document("$or", dateQueries),
new Document("$or", workflowCriteria)
));

List<Document> workflowCriteria = new ArrayList<>();
workflowCriteria.add(new Document(WORKFLOW_TYPE, new Document("$nin", NOT_ALLOWED_WORKFLOWS_FOR_INSTITUTION_NOTIFICATIONS.stream().map(Enum::name).toList())));
workflowCriteria.add(new Document(WORKFLOW_TYPE, new Document("$exists", false)));
query.append("$or", workflowCriteria);
return query;
}

private List<Document> createDateQueries(ResendNotificationsFilters filters) {
return Stream.of(
createIntervalQueryForDate(filters, ACTIVATED_AT_FIELD),
createIntervalQueryForDate(filters, DELETED_AT_FIELD)
).filter(doc -> !doc.isEmpty()).toList();
}

private Document createIntervalQueryForDate(ResendNotificationsFilters filters, String dateField) {
Document dateQuery = new Document();
Optional.ofNullable(filters.getFrom()).ifPresent(value -> dateQuery.append("$gte", LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE)));
Optional.ofNullable(filters.getTo()).ifPresent(value -> dateQuery.append("$lte", LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE).plusDays(1)));
return new Document(dateField, dateQuery);
}

private List<Document> createWorkflowCriteria() {
return List.of(
new Document(WORKFLOW_TYPE, new Document("$nin", NOT_ALLOWED_WORKFLOWS_FOR_INSTITUTION_NOTIFICATIONS.stream().map(Enum::name).toList())),
new Document(WORKFLOW_TYPE, new Document("$exists", false))
);
}

static class SendMailInput {
Product product;
String userRequestName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package it.pagopa.selfcare.onboarding.utils;

public class CustomMetricsConst {
private CustomMetricsConst() {
}

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_SUCCESS = "EventsOnboardingInstitution_success";

}
Loading

0 comments on commit e15e95c

Please sign in to comment.