Example #1
0
        /// <summary>
        /// Updates the note watch notification digest.
        /// </summary>
        /// <param name="personIdNotificationDigestList">The person identifier notification digest list.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="noteId">The note identifier.</param>
        private void UpdateNoteWatchNotificationDigest(Dictionary <int, NoteWatchPersonToNotifyList> personIdNotificationDigestList, RockContext rockContext, int noteId)
        {
            var noteService = new Rock.Model.NoteService(rockContext);

            var note = noteService.Queryable().Include(a => a.EditedByPersonAlias).FirstOrDefault(a => a.Id == noteId);

            if (note == null || !note.EntityId.HasValue)
            {
                // shouldn't' happen
                return;
            }

            var noteType = NoteTypeCache.Get(note.NoteTypeId);

            // make sure the note's notetype has an EntityTypeId (is should, but just in case it doesn't)
            int?noteEntityTypeId = noteType?.EntityTypeId;

            if (!noteEntityTypeId.HasValue)
            {
                return;
            }

            var noteWatchService = new Rock.Model.NoteWatchService(rockContext);

            // narrow it down to NoteWatches for the same EntityType as the Note
            var noteWatchesQuery = noteWatchService.Queryable()
                                   .Where(a =>
                                          (a.EntityTypeId.HasValue && a.EntityTypeId.Value == noteEntityTypeId.Value) ||
                                          (a.NoteTypeId.HasValue && a.NoteType.EntityTypeId == noteEntityTypeId));

            // narrow it down to either note watches on..
            // 1) specific Entity
            // 2) specific Note
            // 3) any note of the NoteType
            // 4) any note on the EntityType

            // specific Entity
            noteWatchesQuery = noteWatchesQuery.Where(a =>
                                                      (a.EntityId == null) ||
                                                      (note.EntityId.HasValue && a.EntityId.Value == note.EntityId.Value));

            // or specifically for this Note's ParentNote (a reply to the Note)
            noteWatchesQuery = noteWatchesQuery.Where(a =>
                                                      (a.NoteId == null) ||
                                                      (note.ParentNoteId.HasValue && a.NoteId.Value == note.ParentNoteId));

            // or specifically for this note's note type
            noteWatchesQuery = noteWatchesQuery.Where(a =>
                                                      (a.NoteTypeId == null) ||
                                                      (a.NoteTypeId.Value == note.NoteTypeId));

            // if there are any NoteWatches that relate to this note, process them
            if (noteWatchesQuery.Any())
            {
                var noteWatchesForNote = noteWatchesQuery.Include(a => a.WatcherPersonAlias.Person).AsNoTracking().ToList();
                List <NoteWatchPersonToNotify> noteWatchPersonToNotifyListAll = new List <NoteWatchPersonToNotify>();

                // loop thru Watches to get a list of people to possibly notify/override
                foreach (var noteWatch in noteWatchesForNote)
                {
                    // if a specific person is the watcher, add them
                    var watcherPerson = noteWatch.WatcherPersonAlias?.Person;
                    if (watcherPerson != null)
                    {   // Since this is iterated do not add the person to the list if they are already there.
                        var exists = noteWatchPersonToNotifyListAll.Where(p => p.Person.Email.Contains(watcherPerson.Email)).Any();
                        if (!exists)
                        {
                            noteWatchPersonToNotifyListAll.Add(new NoteWatchPersonToNotify(watcherPerson, note, noteWatch));
                        }
                    }

                    if (noteWatch.WatcherGroupId.HasValue)
                    {
                        var watcherPersonsFromGroup = new GroupMemberService(rockContext).Queryable()
                                                      .Where(a => a.GroupMemberStatus == GroupMemberStatus.Active && a.GroupId == noteWatch.WatcherGroupId.Value)
                                                      .Select(a => a.Person).ToList();

                        if (watcherPersonsFromGroup.Any())
                        {
                            // Do not add people from the group that are already added.
                            var distinctWatchers = watcherPersonsFromGroup.Where(wg => !noteWatchPersonToNotifyListAll.Where(w => w.Person.Email.Contains(wg.Email)).Any());
                            noteWatchPersonToNotifyListAll.AddRange(distinctWatchers.Select(a => new NoteWatchPersonToNotify(a, note, noteWatch)));
                        }
                    }
                }

                var noteWatchPersonToNotifyList = noteWatchPersonToNotifyListAll.Where(a => a.NoteWatch.IsWatching).ToList();
                var noteWatchPersonToNotifyListWatchDisabled = noteWatchPersonToNotifyListAll.Where(a => !a.NoteWatch.IsWatching).ToList();
                var noteWatchPersonToNotifyListNoOverride    = noteWatchPersonToNotifyList.Where(a => a.NoteWatch.AllowOverride == false).ToList();

                foreach (var noteWatchPersonToNotify in noteWatchPersonToNotifyList)
                {
                    // check if somebody wanted to specifically NOT watch this (and there isn't another watch that prevents overrides)
                    if (noteWatchPersonToNotifyListWatchDisabled.Any(a => a.Person.Id == noteWatchPersonToNotify.Person.Id))
                    {
                        // Person Requested to NOT watch, now make sure that they aren't force to watch based on Override = False
                        if (!noteWatchPersonToNotifyListNoOverride.Any(a => a.Person.Id == noteWatchPersonToNotify.Person.Id))
                        {
                            // person requested to NOT watch, and there aren't any overrides to prevent that, so jump out to the next one
                            continue;
                        }
                    }

                    NoteWatchPersonToNotifyList personToNotifyList;
                    if (personIdNotificationDigestList.ContainsKey(noteWatchPersonToNotify.Person.Id))
                    {
                        // This just create a place holder for the Note referring to item in the digest by key of person
                        personToNotifyList = personIdNotificationDigestList[noteWatchPersonToNotify.Person.Id] ?? new NoteWatchPersonToNotifyList(noteWatchPersonToNotify.Person);
                    }
                    else
                    {
                        // This just creates  a new place holder for the Note in the digest
                        personToNotifyList = new NoteWatchPersonToNotifyList(noteWatchPersonToNotify.Person);
                        personIdNotificationDigestList.Add(noteWatchPersonToNotify.Person.Id, personToNotifyList);
                    }

                    // Only include the note if the watcher person is authorized to view the note
                    if (noteWatchPersonToNotify.Note.IsAuthorized(Rock.Security.Authorization.VIEW, noteWatchPersonToNotify.Person))
                    {
                        // This is where the get added to the item of the digest
                        personToNotifyList.Add(noteWatchPersonToNotify);
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Sends the note approval notifications.
        /// </summary>
        /// <param name="context">The context.</param>
        private List <string> SendNoteApprovalNotifications(IJobExecutionContext context)
        {
            var        errors = new List <string>();
            List <int> noteIdsToProcessApprovalsList = new List <int>();

            using (var rockContext = new RockContext())
            {
                var noteService = new Rock.Model.NoteService(rockContext);

                // get all notes that are pending approval and haven't sent approval notifications yet
                var notesThatNeedApprovalNotifyQuery = noteService.Queryable().Where(a =>
                                                                                     a.NoteType.RequiresApprovals &&
                                                                                     a.NoteType.SendApprovalNotifications &&
                                                                                     a.ApprovalsSent == false &&
                                                                                     a.ApprovalStatus == NoteApprovalStatus.PendingApproval &&
                                                                                     a.EditedDateTime > _cutoffNoteEditDateTime);

                if (!notesThatNeedApprovalNotifyQuery.Any())
                {
                    // there aren't any notes that haven't had approval notifications processed yet
                    return(errors);
                }

                noteIdsToProcessApprovalsList = notesThatNeedApprovalNotifyQuery.Select(a => a.Id).ToList();
            }

            using (var rockContext = new RockContext())
            {
                // get the approvers for each notetypeId
                Dictionary <int, List <Person> > noteTypeApprovers = new Dictionary <int, List <Person> >();

                NoteTypeService noteTypeService     = new NoteTypeService(rockContext);
                var             noteTypeIdsForNotes = new NoteService(rockContext).Queryable()
                                                      .Where(a => noteIdsToProcessApprovalsList.Contains(a.Id)).Select(a => a.NoteTypeId).Distinct().ToList();

                foreach (var noteTypeId in noteTypeIdsForNotes)
                {
                    var approvers = noteTypeService.GetApprovers(noteTypeId).ToList();
                    noteTypeApprovers.Add(noteTypeId, approvers);
                }

                // make a list of notes for each approver so we can send a digest of notes to approve to each approver
                Dictionary <Person, List <Note> > approverNotesToApproveList = new Dictionary <Person, List <Note> >();
                foreach (var noteId in noteIdsToProcessApprovalsList)
                {
                    var noteService      = new Rock.Model.NoteService(rockContext);
                    var note             = noteService.Get(noteId);
                    var approversForNote = noteTypeApprovers.GetValueOrNull(note.NoteTypeId);
                    if (approversForNote?.Any() == true)
                    {
                        List <Note> notesToApprove;
                        foreach (Person approverPerson in approversForNote)
                        {
                            if (approverNotesToApproveList.ContainsKey(approverPerson))
                            {
                                notesToApprove = approverNotesToApproveList[approverPerson] ?? new List <Note>();
                            }
                            else
                            {
                                notesToApprove = new List <Note>();
                                approverNotesToApproveList.Add(approverPerson, notesToApprove);
                            }

                            notesToApprove.Add(note);
                        }
                    }
                    else
                    {
                        // if there are no approvers for this note type, leave it as pending approval
                    }
                }

                if (!approverNotesToApproveList.Any())
                {
                    // nothing to do so exit
                    return(errors);
                }

                // send approval emails
                var recipients = new List <RecipientData>();
                foreach (var approverNotesToApprove in approverNotesToApproveList)
                {
                    Person      approverPerson = approverNotesToApprove.Key;
                    List <Note> noteList       = approverNotesToApprove.Value;
                    if (!string.IsNullOrEmpty(approverPerson.Email) && approverPerson.IsEmailActive && noteList.Any())
                    {
                        var mergeFields = new Dictionary <string, object>(_defaultMergeFields);
                        mergeFields.Add("ApproverPerson", approverPerson);
                        mergeFields.Add("NoteList", noteList);
                        recipients.Add(new RecipientData(approverPerson.Email, mergeFields));
                    }

                    if (_noteApprovalNotificationEmailGuid.HasValue)
                    {
                        var emailMessage = new RockEmailMessage(_noteApprovalNotificationEmailGuid.Value);
                        emailMessage.SetRecipients(recipients);
                        emailMessage.Send(out errors);
                        _noteApprovalNotificationsSent += recipients.Count();

                        using (var rockUpdateContext = new RockContext())
                        {
                            var noteListIds             = noteList.Select(a => a.Id).ToList();
                            var notesToMarkApprovalSent = new NoteService(rockUpdateContext).Queryable().Where(a => noteListIds.Contains(a.Id));

                            // use BulkUpdate to mark all the notes that we processed to ApprovalsSent = true
                            rockUpdateContext.BulkUpdate(notesToMarkApprovalSent, n => new Note {
                                ApprovalsSent = true
                            });
                        }
                    }
                }
            }

            return(errors);
        }