/// <summary> /// Sends the meeting reminders. /// </summary> /// <param name="context">The overall job context.</param> /// <param name="rockContext">The rockContext.</param> /// <param name="occurrenceData">The occurrenceData to process.</param> /// <param name="systemCommunication">The system communication.</param> /// <param name="jobPreferredCommunicationType">Type of the job preferred communication.</param> /// <returns></returns> private SendMessageResult SendMeetingReminders(IJobExecutionContext context, RockContext rockContext, Dictionary <RoomOccurrence, Group> occurrenceData, SystemCommunication systemCommunication, CommunicationType jobPreferredCommunicationType, bool isSmsEnabled, bool isPushEnabled) { var result = new SendMessageResult(); var errorsEmail = new List <string>(); var errorsSms = new List <string>(); var errorsPush = new List <string>(); // Loop through the room occurrence data foreach (var occurrence in occurrenceData) { var emailMessage = new RockEmailMessage(systemCommunication); RockSMSMessage smsMessage = isSmsEnabled ? new RockSMSMessage(systemCommunication) : null; RockPushMessage pushMessage = isPushEnabled ? new RockPushMessage(systemCommunication) : null; var group = occurrence.Value; foreach (var groupMember in group.ActiveMembers().ToList()) { groupMember.Person.LoadAttributes(); var smsNumber = groupMember.Person.PhoneNumbers.GetFirstSmsNumber(); var personAlias = new PersonAliasService(rockContext).Get(groupMember.Person.PrimaryAliasId.Value); List <string> pushDevices = new PersonalDeviceService(rockContext).Queryable() .Where(a => a.PersonAliasId.HasValue && a.PersonAliasId == personAlias.Id && a.NotificationsEnabled) .Select(a => a.DeviceRegistrationId) .ToList(); if (!groupMember.Person.CanReceiveEmail(false) && smsNumber.IsNullOrWhiteSpace() && pushDevices.Count == 0) { continue; } var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null, groupMember.Person); mergeFields.Add("Group", group); mergeFields.Add("Occurrence", occurrence.Key); mergeFields.Add("Person", groupMember.Person); var notificationType = ( CommunicationType )Communication.DetermineMediumEntityTypeId( ( int )CommunicationType.Email, ( int )CommunicationType.SMS, ( int )CommunicationType.PushNotification, jobPreferredCommunicationType, groupMember.CommunicationPreference, groupMember.Person.CommunicationPreference); switch (notificationType) { case CommunicationType.Email: if (!groupMember.Person.CanReceiveEmail(false)) { errorCount += 1; errorMessages.Add(string.Format("{0} does not have a valid email address.", groupMember.Person.FullName)); } else { emailMessage.AddRecipient(new RockEmailMessageRecipient(groupMember.Person, mergeFields)); } break; case CommunicationType.SMS: if (string.IsNullOrWhiteSpace(smsNumber) || smsMessage == null) { errorCount += 1; errorMessages.Add(string.Format("No SMS number could be found for {0}.", groupMember.Person.FullName)); goto case CommunicationType.Email; } else { smsMessage.AddRecipient(new RockSMSMessageRecipient(groupMember.Person, smsNumber, mergeFields)); } break; case CommunicationType.PushNotification: if (pushDevices.Count == 0 || pushMessage == null) { errorCount += 1; errorMessages.Add(string.Format("No devices that support notifications could be found for {0}.", groupMember.Person.FullName)); goto case CommunicationType.Email; } else { string deviceIds = String.Join(",", pushDevices); pushMessage.AddRecipient(new RockPushMessageRecipient(groupMember.Person, deviceIds, mergeFields)); } break; default: break; } } if (emailMessage.GetRecipients().Count > 0) { emailMessage.Send(out errorsEmail); if (errorsEmail.Any()) { result.Errors.AddRange(errorsEmail); } else { notificationEmails++; } } if (smsMessage != null && smsMessage.GetRecipients().Count > 0) { smsMessage.Send(out errorsSms); if (errorsSms.Any()) { result.Errors.AddRange(errorsSms); } else { notificationSms++; } } if (pushMessage != null && pushMessage.GetRecipients().Count > 0) { pushMessage.Send(out errorsPush); if (errorsPush.Any()) { result.Errors.AddRange(errorsPush); } else { notificationPush++; } } } if (errorMessages.Any()) { StringBuilder sb = new StringBuilder(); sb.AppendLine(); sb.Append(string.Format("{0} Errors: ", errorCount)); errorMessages.ForEach(e => { sb.AppendLine(); sb.Append(e); }); string errors = sb.ToString(); context.Result += errors; var exception = new Exception(errors); HttpContext context2 = HttpContext.Current; ExceptionLogService.LogException(exception, context2); throw exception; } return(result); }
/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> public virtual void Execute(IJobExecutionContext context) { var dataMap = context.JobDetail.JobDataMap; var JobStartDateTime = RockDateTime.Now; var minimumCareTouches = dataMap.GetIntegerFromString(AttributeKey.MinimumCareTouches); var minimumCareTouchesHours = dataMap.GetIntegerFromString(AttributeKey.MinimumCareTouches); var followUpDays = dataMap.GetIntegerFromString(AttributeKey.FollowUpDays); using (var rockContext = new RockContext()) { // get the last run date or yesterday DateTime?lastStartDateTime = null; // get job type id int jobId = context.JobDetail.Description.AsInteger(); // load job var job = new ServiceJobService(rockContext) .GetNoTracking(jobId); if (job != null && job.Guid != Rock.SystemGuid.ServiceJob.JOB_PULSE.AsGuid()) { lastStartDateTime = job.LastRunDateTime?.AddSeconds(0.0d - ( double )job.LastRunDurationSeconds); } var beginDateTime = lastStartDateTime ?? JobStartDateTime.AddDays(-1); //beginDateTime = JobStartDateTime.AddDays( -3 ); var careNeedService = new CareNeedService(rockContext); var assignedPersonService = new AssignedPersonService(rockContext); var noteType = NoteTypeCache.GetByEntity(EntityTypeCache.Get(typeof(CareNeed)).Id, "", "", true).FirstOrDefault(); var careNeedNotesQry = new NoteService(rockContext) .GetByNoteTypeId(noteType.Id).AsNoTracking(); var closedValueId = DefinedValueCache.Get(SystemGuid.DefinedValue.CARE_NEED_STATUS_CLOSED.AsGuid()).Id; var followUpValue = DefinedValueCache.Get(SystemGuid.DefinedValue.CARE_NEED_STATUS_FOLLOWUP.AsGuid()); var openValueId = DefinedValueCache.Get(SystemGuid.DefinedValue.CARE_NEED_STATUS_OPEN.AsGuid()).Id; var careNeeds = careNeedService.Queryable("PersonAlias,SubmitterPersonAlias").Where(n => n.StatusValueId != closedValueId); var careAssigned = assignedPersonService.Queryable().Where(ap => ap.PersonAliasId != null && ap.NeedId != null && ap.CareNeed.StatusValueId != closedValueId).DistinctBy(ap => ap.PersonAliasId); var careNeedFollowUp = careNeeds.Where(n => n.StatusValueId == openValueId && n.DateEntered <= DbFunctions.AddDays(RockDateTime.Now, -followUpDays)); var careNeed24Hrs = careNeeds.Where(n => n.StatusValueId == openValueId && DbFunctions.DiffHours(n.DateEntered.Value, RockDateTime.Now) >= minimumCareTouchesHours); var careNeedFlagged = careNeed24Hrs .SelectMany(cn => careNeedNotesQry.Where(n => n.EntityId == cn.Id && cn.AssignedPersons.Any(ap => ap.FollowUpWorker.HasValue && ap.FollowUpWorker.Value && ap.PersonAliasId == n.CreatedByPersonAliasId)).DefaultIfEmpty(), (cn, n) => new { CareNeed = cn, HasFollowUpWorkerNote = n != null, TouchCount = careNeedNotesQry.Where(note => note.EntityId == cn.Id).Count() }) .Where(f => !f.HasFollowUpWorkerNote || f.TouchCount <= minimumCareTouches) .ToList(); var followUpSystemCommunicationGuid = dataMap.GetString(AttributeKey.FollowUpSystemCommunication).AsGuid(); var careTouchNeededCommunicationGuid = dataMap.GetString(AttributeKey.CareTouchNeededCommunication).AsGuid(); var outstandingNeedsCommunicationGuid = dataMap.GetString(AttributeKey.OutstandingNeedsCommunication).AsGuid(); var followUpSystemCommunication = new SystemCommunicationService(rockContext).Get(followUpSystemCommunicationGuid); var careTouchNeededCommunication = new SystemCommunicationService(rockContext).Get(careTouchNeededCommunicationGuid); var outstandingNeedsCommunication = new SystemCommunicationService(rockContext).Get(outstandingNeedsCommunicationGuid); var detailPage = PageCache.Get(dataMap.GetString(AttributeKey.CareDetailPage)); var detailPageRoute = detailPage.PageRoutes.FirstOrDefault(); var dashboardPage = PageCache.Get(dataMap.GetString(AttributeKey.CareDashboardPage)); var dashboardPageRoute = dashboardPage.PageRoutes.FirstOrDefault(); Dictionary <string, object> linkedPages = new Dictionary <string, object>(); linkedPages.Add("CareDetail", detailPageRoute != null ? "/" + detailPageRoute.Route : "/page/" + detailPage.Id); linkedPages.Add("CareDashboard", dashboardPageRoute != null ? "/" + dashboardPageRoute.Route : "/page/" + dashboardPage.Id); var errors = new List <string>(); var errorsSms = new List <string>(); // Update status to follow up and email follow up messages foreach (var careNeed in careNeedFollowUp) { careNeed.StatusValueId = followUpValue.Id; careNeed.LoadAttributes(); if (!followUpSystemCommunicationGuid.IsEmpty()) { var emailMessage = new RockEmailMessage(followUpSystemCommunication); var smsMessage = new RockSMSMessage(followUpSystemCommunication); foreach (var assignee in careNeed.AssignedPersons.Where(ap => ap.FollowUpWorker.HasValue && ap.FollowUpWorker.Value)) { assignee.PersonAlias.Person.LoadAttributes(); var smsNumber = assignee.PersonAlias.Person.PhoneNumbers.GetFirstSmsNumber(); if (!assignee.PersonAlias.Person.CanReceiveEmail(false) && smsNumber.IsNullOrWhiteSpace()) { continue; } var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null, assignee.PersonAlias.Person); mergeFields.Add("CareNeed", careNeed); mergeFields.Add("LinkedPages", linkedPages); mergeFields.Add("AssignedPerson", assignee); mergeFields.Add("Person", assignee.PersonAlias.Person); var recipients = new List <RockMessageRecipient>(); recipients.Add(new RockEmailMessageRecipient(assignee.PersonAlias.Person, mergeFields)); var notificationType = assignee.PersonAlias.Person.GetAttributeValue(SystemGuid.PersonAttribute.NOTIFICATION.AsGuid()); if (notificationType == null || notificationType == "Email" || notificationType == "Both") { if (!assignee.PersonAlias.Person.CanReceiveEmail(false)) { errorCount += 1; errorMessages.Add(string.Format("{0} does not have a valid email address.", assignee.PersonAlias.Person.FullName)); } else { emailMessage.AddRecipient(new RockEmailMessageRecipient(assignee.PersonAlias.Person, mergeFields)); } } if (notificationType == "SMS" || notificationType == "Both") { if (string.IsNullOrWhiteSpace(smsNumber)) { errorCount += 1; errorMessages.Add(string.Format("No SMS number could be found for {0}.", assignee.PersonAlias.Person.FullName)); } smsMessage.AddRecipient(new RockSMSMessageRecipient(assignee.PersonAlias.Person, smsNumber, mergeFields)); } //pushMessage.AddRecipient( new RockPushMessageRecipient( assignee.PersonAlias.Person, assignee.PersonAlias.Person.Devices, mergeFields ) ); } if (emailMessage.GetRecipients().Count > 0) { emailMessage.Send(out errors); } if (smsMessage.GetRecipients().Count > 0) { smsMessage.Send(out errorsSms); } if (errors.Any()) { errorCount += errors.Count; errorMessages.AddRange(errors); } else { assignedPersonEmails++; } if (errorsSms.Any()) { errorCount += errorsSms.Count; errorMessages.AddRange(errorsSms); } else { assignedPersonSms++; } } } rockContext.SaveChanges(); // Send notification about "Flagged" messages (any messages without a care touch by the follow up worker or minimum care touches within the set minimum Care Touches Hours. if (careTouchNeededCommunication != null && careTouchNeededCommunication.Id > 0) { foreach (var flagNeed in careNeedFlagged) { var careNeed = flagNeed.CareNeed; careNeed.LoadAttributes(); var emailMessage = new RockEmailMessage(careTouchNeededCommunication); var smsMessage = new RockSMSMessage(careTouchNeededCommunication); //var pushMessage = new RockPushMessage( careTouchNeededCommunication ); var recipients = new List <RockMessageRecipient>(); foreach (var assignee in careNeed.AssignedPersons) { assignee.PersonAlias.Person.LoadAttributes(); var smsNumber = assignee.PersonAlias.Person.PhoneNumbers.GetFirstSmsNumber(); if (!assignee.PersonAlias.Person.CanReceiveEmail(false) && smsNumber.IsNullOrWhiteSpace()) { continue; } var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null, assignee.PersonAlias.Person); mergeFields.Add("CareNeed", careNeed); mergeFields.Add("LinkedPages", linkedPages); mergeFields.Add("AssignedPerson", assignee); mergeFields.Add("Person", assignee.PersonAlias.Person); mergeFields.Add("TouchCount", flagNeed.TouchCount); mergeFields.Add("HasFollowUpWorkerNote", flagNeed.HasFollowUpWorkerNote); var notificationType = assignee.PersonAlias.Person.GetAttributeValue(SystemGuid.PersonAttribute.NOTIFICATION.AsGuid()); if (notificationType == null || notificationType == "Email" || notificationType == "Both") { if (!assignee.PersonAlias.Person.CanReceiveEmail(false)) { errorCount += 1; errorMessages.Add(string.Format("{0} does not have a valid email address.", assignee.PersonAlias.Person.FullName)); } else { emailMessage.AddRecipient(new RockEmailMessageRecipient(assignee.PersonAlias.Person, mergeFields)); } } if (notificationType == "SMS" || notificationType == "Both") { if (string.IsNullOrWhiteSpace(smsNumber)) { errorCount += 1; errorMessages.Add(string.Format("No SMS number could be found for {0}.", assignee.PersonAlias.Person.FullName)); } smsMessage.AddRecipient(new RockSMSMessageRecipient(assignee.PersonAlias.Person, smsNumber, mergeFields)); } //pushMessage.AddRecipient( new RockPushMessageRecipient( assignee.PersonAlias.Person, assignee.PersonAlias.Person.Devices, mergeFields ) ); } if (emailMessage.GetRecipients().Count > 0) { emailMessage.Send(out errors); } if (smsMessage.GetRecipients().Count > 0) { smsMessage.Send(out errorsSms); } if (errors.Any()) { errorCount += errors.Count; errorMessages.AddRange(errors); } else { assignedPersonEmails++; } if (errorsSms.Any()) { errorCount += errorsSms.Count; errorMessages.AddRange(errorsSms); } else { assignedPersonSms++; } } } // Send Outstanding needs daily notification if (outstandingNeedsCommunication != null && outstandingNeedsCommunication.Id > 0) { foreach (var assigned in careAssigned) { var smsNumber = assigned.PersonAlias.Person.PhoneNumbers.GetFirstSmsNumber(); if (!assigned.PersonAlias.Person.CanReceiveEmail(false) && smsNumber.IsNullOrWhiteSpace()) { continue; } var emailMessage = new RockEmailMessage(outstandingNeedsCommunication); var smsMessage = new RockSMSMessage(outstandingNeedsCommunication); //var pushMessage = new RockPushMessage( outstandingNeedsCommunication ); var recipients = new List <RockMessageRecipient>(); var assignedNeeds = careNeeds.Where(cn => cn.AssignedPersons.Any(ap => ap.PersonAliasId == assigned.PersonAliasId)); assigned.PersonAlias.Person.LoadAttributes(); var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null, assigned.PersonAlias.Person); mergeFields.Add("CareNeeds", assignedNeeds); mergeFields.Add("LinkedPages", linkedPages); mergeFields.Add("AssignedPerson", assigned); mergeFields.Add("Person", assigned.PersonAlias.Person); var notificationType = assigned.PersonAlias.Person.GetAttributeValue(SystemGuid.PersonAttribute.NOTIFICATION.AsGuid()); if (notificationType == null || notificationType == "Email" || notificationType == "Both") { if (!assigned.PersonAlias.Person.CanReceiveEmail(false)) { errorCount += 1; errorMessages.Add(string.Format("{0} does not have a valid email address.", assigned.PersonAlias.Person.FullName)); } else { emailMessage.AddRecipient(new RockEmailMessageRecipient(assigned.PersonAlias.Person, mergeFields)); } } if (notificationType == "SMS" || notificationType == "Both") { if (string.IsNullOrWhiteSpace(smsNumber)) { errorCount += 1; errorMessages.Add(string.Format("No SMS number could be found for {0}.", assigned.PersonAlias.Person.FullName)); } smsMessage.AddRecipient(new RockSMSMessageRecipient(assigned.PersonAlias.Person, smsNumber, mergeFields)); } //pushMessage.AddRecipient( new RockPushMessageRecipient( assignee.PersonAlias.Person, assignee.PersonAlias.Person.Devices, mergeFields ) ); if (emailMessage.GetRecipients().Count > 0) { emailMessage.Send(out errors); } if (smsMessage.GetRecipients().Count > 0) { smsMessage.Send(out errorsSms); } if (errors.Any()) { errorCount += errors.Count; errorMessages.AddRange(errors); } else { assignedPersonEmails++; } if (errorsSms.Any()) { errorCount += errorsSms.Count; errorMessages.AddRange(errorsSms); } else { assignedPersonSms++; } } } } context.Result = string.Format("{0} emails sent \n{1} SMS messages sent", assignedPersonEmails, assignedPersonSms); if (errorMessages.Any()) { StringBuilder sb = new StringBuilder(); sb.AppendLine(); sb.Append(string.Format("{0} Errors: ", errorCount)); errorMessages.ForEach(e => { sb.AppendLine(); sb.Append(e); }); string errors = sb.ToString(); context.Result += errors; var exception = new Exception(errors); HttpContext context2 = HttpContext.Current; ExceptionLogService.LogException(exception, context2); throw exception; } }