Example #1
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);
        }
Example #2
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);
                    }
                }
            }
        }
        /// <summary>
        /// Saves the person notes and history.
        /// </summary>
        /// <param name="registrationPersonFirstName">First name of the registration person.</param>
        /// <param name="registrationPersonLastName">Last name of the registration person.</param>
        /// <param name="currentPersonAliasId">The current person alias identifier.</param>
        /// <param name="previousRegistrantPersonIds">The previous registrant person ids.</param>
        public void SavePersonNotesAndHistory(string registrationPersonFirstName, string registrationPersonLastName, int?currentPersonAliasId, List <int> previousRegistrantPersonIds)
        {
            // Setup Note settings
            Registration  registration = this;
            NoteTypeCache noteType     = null;

            using (RockContext rockContext = new RockContext())
            {
                RegistrationInstance registrationInstance = registration.RegistrationInstance ?? new RegistrationInstanceService(rockContext).Get(registration.RegistrationInstanceId);
                RegistrationTemplate registrationTemplate = registrationInstance.RegistrationTemplate ?? new RegistrationTemplateService(rockContext).Get(registrationInstance.RegistrationTemplateId);

                if (registrationTemplate != null && registrationTemplate.AddPersonNote)
                {
                    noteType = NoteTypeCache.Get(Rock.SystemGuid.NoteType.PERSON_EVENT_REGISTRATION.AsGuid());
                    if (noteType != null)
                    {
                        var noteService        = new NoteService(rockContext);
                        var personAliasService = new PersonAliasService(rockContext);

                        Person registrar = null;
                        if (registration.PersonAliasId.HasValue)
                        {
                            registrar = personAliasService.GetPerson(registration.PersonAliasId.Value);
                        }

                        var registrantNames = new List <string>();

                        // Get each registrant
                        foreach (var registrantPersonAliasId in registration.Registrants
                                 .Where(r => r.PersonAliasId.HasValue)
                                 .Select(r => r.PersonAliasId.Value)
                                 .ToList())
                        {
                            var registrantPerson = personAliasService.GetPerson(registrantPersonAliasId);
                            if (registrantPerson != null && (previousRegistrantPersonIds == null || !previousRegistrantPersonIds.Contains(registrantPerson.Id)))
                            {
                                var noteText = new StringBuilder();
                                noteText.AppendFormat("Registered for {0}", registrationInstance.Name);

                                string registrarFullName = string.Empty;

                                if (registrar != null && registrar.Id != registrantPerson.Id)
                                {
                                    registrarFullName = string.Format(" by {0}", registrar.FullName);
                                    registrantNames.Add(registrantPerson.FullName);
                                }

                                if (registrar != null && (registrationPersonFirstName != registrar.NickName || registrationPersonLastName != registrar.LastName))
                                {
                                    registrarFullName = string.Format(" by {0}", registrationPersonFirstName + " " + registrationPersonLastName);
                                }

                                noteText.Append(registrarFullName);

                                if (noteText.Length > 0)
                                {
                                    var note = new Note();
                                    note.NoteTypeId    = noteType.Id;
                                    note.IsSystem      = false;
                                    note.IsAlert       = false;
                                    note.IsPrivateNote = false;
                                    note.EntityId      = registrantPerson.Id;
                                    note.Caption       = string.Empty;
                                    note.Text          = noteText.ToString();
                                    if (registrar == null)
                                    {
                                        note.CreatedByPersonAliasId = currentPersonAliasId;
                                    }
                                    else
                                    {
                                        note.CreatedByPersonAliasId = registrar.PrimaryAliasId;
                                    }

                                    noteService.Add(note);
                                }

                                var changes = new History.HistoryChangeList();
                                changes.AddChange(History.HistoryVerb.Registered, History.HistoryChangeType.Record, null);
                                HistoryService.SaveChanges(
                                    rockContext,
                                    typeof(Person),
                                    Rock.SystemGuid.Category.HISTORY_PERSON_REGISTRATION.AsGuid(),
                                    registrantPerson.Id,
                                    changes,
                                    registrationInstance.Name,
                                    typeof(Registration),
                                    registration.Id,
                                    false,
                                    currentPersonAliasId,
                                    rockContext.SourceOfChange);
                            }
                        }

                        if (registrar != null && registrantNames.Any())
                        {
                            string namesText = string.Empty;
                            if (registrantNames.Count >= 2)
                            {
                                int lessOne = registrantNames.Count - 1;
                                namesText = registrantNames.Take(lessOne).ToList().AsDelimited(", ") +
                                            " and " +
                                            registrantNames.Skip(lessOne).Take(1).First() + " ";
                            }
                            else
                            {
                                namesText = registrantNames.First() + " ";
                            }

                            var note = new Note();
                            note.NoteTypeId    = noteType.Id;
                            note.IsSystem      = false;
                            note.IsAlert       = false;
                            note.IsPrivateNote = false;
                            note.EntityId      = registrar.Id;
                            note.Caption       = string.Empty;
                            note.Text          = string.Format("Registered {0} for {1}", namesText, registrationInstance.Name);
                            noteService.Add(note);

                            var changes = new History.HistoryChangeList();
                            changes.AddChange(History.HistoryVerb.Registered, History.HistoryChangeType.Record, namesText);

                            HistoryService.SaveChanges(
                                rockContext,
                                typeof(Person),
                                Rock.SystemGuid.Category.HISTORY_PERSON_REGISTRATION.AsGuid(),
                                registrar.Id,
                                changes,
                                registrationInstance.Name,
                                typeof(Registration),
                                registration.Id,
                                false,
                                currentPersonAliasId,
                                rockContext.SourceOfChange);
                        }

                        rockContext.SaveChanges();
                    }
                }
            }
        }