/// <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); }