Пример #1
0
        public async Task GenerateNotificationsAsync_With1EventFor1UsersWhoIsNotAttending_SendsNoEmail()
        {
            // Arrange
            List <Event> events = GetEventList1();
            List <User>  users  = GetUserList1();

            EventRepository.Setup(e => e.GetActiveEvents(It.IsAny <CancellationToken>())).ReturnsAsync(events);
            UserRepository.Setup(u => u.GetAllUsers(It.IsAny <CancellationToken>())).ReturnsAsync(users);

            // Act
            await Engine.GenerateNotificationsAsync().ConfigureAwait(false);

            // Assert
            UserRepository.Verify(_ => _.GetAllUsers(It.IsAny <CancellationToken>()), Times.Once);
            UserNotificationPreferenceRepository.Verify(_ => _.GetUserNotificationPreferences(It.IsAny <Guid>(), It.IsAny <CancellationToken>()), Times.Once);
            EventRepository.Verify(_ => _.GetActiveEvents(It.IsAny <CancellationToken>()), Times.Once);
            EventAttendeeRepository.Verify(_ => _.GetEventsUserIsAttending(It.IsAny <Guid>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()), Times.Once);
            UserNotificationRepository.Verify(_ => _.AddUserNotification(It.IsAny <UserNotification>()), Times.Never);
            EmailSender.Verify(_ => _.SendEmailAsync(It.IsAny <Email>(), It.IsAny <CancellationToken>()), Times.Never);
        }
        public async Task GenerateNotificationsAsync_With1EventFor1UsersWhereEventIsMoreThanRequiredHoursAway_SendsNoEmail()
        {
            // Arrange
            List <Event> events = GetEventList1();
            List <User>  users  = GetUserList1();

            events[0].EventDate = DateTimeOffset.UtcNow.AddDays(NumberOfDaysToAddForEventOutOfWindow);

            EventRepository.Setup(e => e.GetActiveEvents(It.IsAny <CancellationToken>())).ReturnsAsync(events);
            UserRepository.Setup(u => u.GetAllUsers(It.IsAny <CancellationToken>())).ReturnsAsync(users);

            // Act
            await Engine.GenerateNotificationsAsync().ConfigureAwait(false);

            // Assert
            UserRepository.Verify(_ => _.GetAllUsers(It.IsAny <CancellationToken>()), Times.Once);
            EventRepository.Verify(_ => _.GetActiveEvents(It.IsAny <CancellationToken>()), Times.Once);
            UserNotificationPreferenceRepository.Verify(_ => _.GetUserNotificationPreferences(It.IsAny <Guid>(), It.IsAny <CancellationToken>()), Times.Once);
            EventAttendeeRepository.Verify(_ => _.GetEventsUserIsAttending(It.IsAny <Guid>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()), Times.Once);
            UserNotificationRepository.Verify(_ => _.AddUserNotification(It.IsAny <UserNotification>()), Times.Never);
            EmailSender.Verify(_ => _.SendEmailAsync(It.IsAny <Email>(), It.IsAny <CancellationToken>()), Times.Never);
        }
        public async Task GenerateNotificationsAsync_With1EventFor1UsersWhoHasAlreadyReceivedTheEmail_SendsNoEmail()
        {
            // Arrange
            List <Event> events = GetEventList1();
            List <User>  users  = GetUserList1();

            events[0].CreatedByUserId = users[0].Id;

            // The user is attending all available events
            EventAttendeeRepository.Setup(ea => ea.GetEventsUserIsAttending(It.IsAny <Guid>(), It.IsAny <bool>(), It.IsAny <CancellationToken>())).ReturnsAsync(events);
            EventRepository.Setup(e => e.GetActiveEvents(It.IsAny <CancellationToken>())).ReturnsAsync(events);
            UserRepository.Setup(u => u.GetAllUsers(It.IsAny <CancellationToken>())).ReturnsAsync(users);

            // The user has already received notifications for all events
            var userNotification = new UserNotification()
            {
                EventId  = events[0].Id,
                UserId   = users[0].Id,
                SentDate = DateTimeOffset.UtcNow.AddDays(-1),
                UserNotificationTypeId = (int)NotificationType,
            };

            var userNotifications = new List <UserNotification>()
            {
                userNotification
            };

            UserNotificationRepository.Setup(ea => ea.GetUserNotifications(It.IsAny <Guid>(), It.IsAny <Guid>(), It.IsAny <CancellationToken>())).ReturnsAsync(userNotifications);

            // Act
            await Engine.GenerateNotificationsAsync().ConfigureAwait(false);

            // Assert
            UserRepository.Verify(_ => _.GetAllUsers(It.IsAny <CancellationToken>()), Times.Once);
            UserNotificationPreferenceRepository.Verify(_ => _.GetUserNotificationPreferences(It.IsAny <Guid>(), It.IsAny <CancellationToken>()), Times.Once);
            EventRepository.Verify(_ => _.GetActiveEvents(It.IsAny <CancellationToken>()), Times.Once);
            UserNotificationRepository.Verify(_ => _.AddUserNotification(It.IsAny <UserNotification>()), Times.Never);
            EmailSender.Verify(_ => _.SendEmailAsync(It.IsAny <Email>(), It.IsAny <CancellationToken>()), Times.Never);
        }
        public async Task GenerateNotificationsAsync_With1EventFor2Users_Sends1Email()
        {
            // Arrange
            List <Event> events = GetEventList1();
            List <User>  users  = GetUserList2();

            events[0].CreatedByUserId = users[0].Id;

            // The users are attending all available events
            EventAttendeeRepository.Setup(ea => ea.GetEventsUserIsAttending(It.IsAny <Guid>(), It.IsAny <bool>(), It.IsAny <CancellationToken>())).ReturnsAsync(events);
            EventRepository.Setup(e => e.GetActiveEvents(It.IsAny <CancellationToken>())).ReturnsAsync(events);
            UserRepository.Setup(u => u.GetAllUsers(It.IsAny <CancellationToken>())).ReturnsAsync(users);

            // Act
            await Engine.GenerateNotificationsAsync().ConfigureAwait(false);

            // Assert
            UserRepository.Verify(_ => _.GetAllUsers(It.IsAny <CancellationToken>()), Times.Once);
            UserNotificationPreferenceRepository.Verify(_ => _.GetUserNotificationPreferences(It.IsAny <Guid>(), It.IsAny <CancellationToken>()), Times.Exactly(2));
            EventRepository.Verify(_ => _.GetActiveEvents(It.IsAny <CancellationToken>()), Times.Exactly(2));
            UserNotificationRepository.Verify(_ => _.AddUserNotification(It.IsAny <UserNotification>()), Times.Once);
            EmailSender.Verify(_ => _.SendEmailAsync(It.IsAny <Email>(), It.IsAny <CancellationToken>()), Times.Once);
        }
        public async Task GenerateNotificationsAsync(CancellationToken cancellationToken = default)
        {
            Logger.LogInformation("Generating Notifications for {0}", NotificationType);

            // Get list of users who have notifications turned on for locations
            var users = await UserRepository.GetAllUsers(cancellationToken).ConfigureAwait(false);

            int notificationCounter = 0;

            Logger.LogInformation("Generating {0} Notifications for {1} total users", NotificationType, users.Count());

            // for each user
            foreach (var user in users)
            {
                if (await IsOptedOut(user).ConfigureAwait(false))
                {
                    continue;
                }

                // If the user has not set their latitude and longitude, skip user
                if (user.Latitude == 0 && user.Longitude == 0)
                {
                    continue;
                }

                var eventsToNotifyUserFor = new List <Event>();

                // Get list of active events
                var events = await EventRepository.GetActiveEvents(cancellationToken).ConfigureAwait(false);

                // Get list of events user is already attending
                var eventsUserIsAttending = await EventAttendeeRepository.GetEventsUserIsAttending(user.Id, cancellationToken : cancellationToken).ConfigureAwait(false);

                // Limit the list of events to process to those in the next window UTC
                foreach (var mobEvent in events.Where(e => e.EventDate <= DateTimeOffset.UtcNow.AddHours(NumberOfHoursInWindow)))
                {
                    // Skip private events
                    if (!mobEvent.IsEventPublic)
                    {
                        continue;
                    }

                    // Verify that the user is not already attending the event. No need to remind them to attend
                    if (eventsUserIsAttending.Any(ea => ea.Id == mobEvent.Id))
                    {
                        continue;
                    }

                    // Only check distance if the user's country and region match the event
                    if (user.Country != mobEvent.Country || user.Region != mobEvent.Region)
                    {
                        continue;
                    }

                    // Get the distance from the User's home location to the event location
                    var userLocation  = new Tuple <double, double>(user.Latitude.Value, user.Longitude.Value);
                    var eventLocation = new Tuple <double, double>(mobEvent.Latitude.Value, mobEvent.Longitude.Value);

                    var distance = await MapRepository.GetDistanceBetweenTwoPoints(userLocation, eventLocation, user.PrefersMetric).ConfigureAwait(false);

                    // If the distance to the event is greater than the User's preference for distance, ignore it
                    if (distance > user.TravelLimitForLocalEvents)
                    {
                        continue;
                    }

                    if (await UserHasAlreadyReceivedNotification(user, mobEvent).ConfigureAwait(false))
                    {
                        continue;
                    }

                    // Add to the event list to be sent
                    eventsToNotifyUserFor.Add(mobEvent);
                }

                // Populate email
                notificationCounter += await SendNotifications(user, eventsToNotifyUserFor, cancellationToken).ConfigureAwait(false);
            }

            Logger.LogInformation("Generating {0} Total {1} Notifications", notificationCounter, NotificationType);
        }