Ejemplo n.º 1
0
        /// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Execute(IJobExecutionContext context)
        {
            context.Result = string.Empty;
            StringBuilder jobSummaryBuilder = new StringBuilder();

            jobSummaryBuilder.AppendLine("Summary:");
            jobSummaryBuilder.AppendLine(string.Empty);

            // Send emails.
            SendExpiredCreditCardNoticesResult sendExpiredCreditCardNoticesResult = SendExpiredCreditCardNotices(context);

            jobSummaryBuilder.AppendLine($"{sendExpiredCreditCardNoticesResult.ExaminedCount} scheduled credit card transaction(s) were examined.");

            // Report any email send successes.
            if (sendExpiredCreditCardNoticesResult.NoticesSentCount > 0 || !sendExpiredCreditCardNoticesResult.EmailSendExceptions.Any())
            {
                jobSummaryBuilder.AppendLine($"<i class='fa fa-circle text-success'></i> {sendExpiredCreditCardNoticesResult.NoticesSentCount } notice(s) sent.");
            }

            context.UpdateLastStatusMessage(jobSummaryBuilder.ToString());

            // Combine all Exceptions encoutered along the way; we'll roll them into an AggregateException below.
            var innerExceptions = new List <Exception>();

            // Report any email send failures.
            if (sendExpiredCreditCardNoticesResult.EmailSendExceptions.Any())
            {
                jobSummaryBuilder.AppendLine($"<i class='fa fa-circle text-danger'></i> {sendExpiredCreditCardNoticesResult.EmailSendExceptions.Count()} error(s) occurred when sending expired credit card notice(s). See exception log for details.");
                context.UpdateLastStatusMessage(jobSummaryBuilder.ToString());

                innerExceptions.AddRange(sendExpiredCreditCardNoticesResult.EmailSendExceptions);
            }

            // Remove expired, saved accounts.
            RemoveExpiredSavedAccountsResult removeExpiredSavedAccountsResult = RemoveExpiredSavedAccounts(context);

            // Report any account removal successes.
            if (removeExpiredSavedAccountsResult.AccountsDeletedCount > 0)
            {
                jobSummaryBuilder.AppendLine($"<i class='fa fa-circle text-success'></i> {removeExpiredSavedAccountsResult.AccountsDeletedCount} saved account(s) that expired before {removeExpiredSavedAccountsResult.DeleteIfExpiredBeforeDate.ToShortDateString()} removed.");
                context.UpdateLastStatusMessage(jobSummaryBuilder.ToString());
            }

            // Report any account removal failures.
            if (removeExpiredSavedAccountsResult.AccountRemovalExceptions.Any())
            {
                jobSummaryBuilder.AppendLine($"<i class='fa fa-circle text-danger'></i> {removeExpiredSavedAccountsResult.AccountRemovalExceptions.Count()} error(s) occurred when removing saved, expired account(s). See exception log for details.");
                context.UpdateLastStatusMessage(jobSummaryBuilder.ToString());

                innerExceptions.AddRange(removeExpiredSavedAccountsResult.AccountRemovalExceptions);
            }

            // If any errors encountered, throw an exception to mark the job as unsuccessful.
            if (innerExceptions.Any())
            {
                var aggregateException = new AggregateException(innerExceptions);

                throw new RockJobWarningException("Send Credit Card Expiration Notices completed with warnings.", aggregateException);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Sends the expired credit card notices.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        /// <exception cref="Exception">Expiring credit card email is missing.</exception>
        private SendExpiredCreditCardNoticesResult SendExpiredCreditCardNotices(IJobExecutionContext context)
        {
            var dataMap     = context.JobDetail.JobDataMap;
            var rockContext = new RockContext();

            // Get the details for the email that we'll be sending out.
            Guid?systemEmailGuid = dataMap.GetString(AttributeKey.ExpiringCreditCardEmail).AsGuidOrNull();
            SystemCommunication systemCommunication = null;

            if (systemEmailGuid.HasValue)
            {
                var systemCommunicationService = new SystemCommunicationService(rockContext);
                systemCommunication = systemCommunicationService.Get(systemEmailGuid.Value);
            }

            if (systemCommunication == null)
            {
                throw new Exception("Expiring credit card email is missing.");
            }

            // Fetch the configured Workflow once if one was set, we'll use it later.
            Guid?workflowGuid = dataMap.GetString(AttributeKey.Workflow).AsGuidOrNull();
            WorkflowTypeCache workflowType    = null;
            WorkflowService   workflowService = new WorkflowService(rockContext);

            if (workflowGuid != null)
            {
                workflowType = WorkflowTypeCache.Get(workflowGuid.Value);
            }

            var financialScheduledTransactionQuery = new FinancialScheduledTransactionService(rockContext).Queryable()
                                                     .Where(t => t.IsActive && t.FinancialPaymentDetail.ExpirationMonthEncrypted != null && (t.EndDate == null || t.EndDate > DateTime.Now))
                                                     .AsNoTracking();

            List <ScheduledTransactionInfo> scheduledTransactionInfoList = financialScheduledTransactionQuery.Select(a => new ScheduledTransactionInfo
            {
                Id = a.Id,
                FinancialPaymentDetail    = a.FinancialPaymentDetail,
                AuthorizedPersonAliasGuid = a.AuthorizedPersonAlias.Guid,
                Person = a.AuthorizedPersonAlias.Person
            }).ToList();

            // Get the current month and year
            DateTime now          = DateTime.Now;
            int      currentMonth = now.Month;
            int      currentYYYY  = now.Year;

            // get the common merge fields once, so we don't have to keep calling it for every person, then create a new mergeFields for each person, starting with a copy of the common merge fields
            var commonMergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null);

            var result = new SendExpiredCreditCardNoticesResult
            {
                ExaminedCount = scheduledTransactionInfoList.Count()
            };

            foreach (ScheduledTransactionInfo scheduledTransactionInfo in scheduledTransactionInfoList.OrderByDescending(a => a.Id))
            {
                int?expirationMonth = scheduledTransactionInfo.FinancialPaymentDetail.ExpirationMonth;
                int?expirationYYYY  = scheduledTransactionInfo.FinancialPaymentDetail.ExpirationYear;
                if (!expirationMonth.HasValue || !expirationMonth.HasValue)
                {
                    continue;
                }

                int warningYear  = expirationYYYY.Value;
                int warningMonth = expirationMonth.Value - 1;
                if (warningMonth == 0)
                {
                    warningYear -= 1;
                    warningMonth = 12;
                }

                if ((warningYear == currentYYYY) && (warningMonth == currentMonth))
                {
                    string maskedCardNumber = string.Empty;

                    if (!string.IsNullOrEmpty(scheduledTransactionInfo.FinancialPaymentDetail.AccountNumberMasked) && scheduledTransactionInfo.FinancialPaymentDetail.AccountNumberMasked.Length >= 4)
                    {
                        maskedCardNumber = scheduledTransactionInfo.FinancialPaymentDetail.AccountNumberMasked.Substring(scheduledTransactionInfo.FinancialPaymentDetail.AccountNumberMasked.Length - 4);
                    }

                    string expirationDateMMYYFormatted = scheduledTransactionInfo.FinancialPaymentDetail?.ExpirationDate;

                    var recipients = new List <RockEmailMessageRecipient>();

                    var person = scheduledTransactionInfo.Person;

                    if (!person.IsEmailActive || person.Email.IsNullOrWhiteSpace() || person.EmailPreference == EmailPreference.DoNotEmail)
                    {
                        continue;
                    }

                    // make a mergeFields for this person, starting with copy of the commonFieldFields
                    var mergeFields = new Dictionary <string, object>(commonMergeFields);
                    mergeFields.Add("Person", person);
                    mergeFields.Add("Card", maskedCardNumber);
                    mergeFields.Add("Expiring", expirationDateMMYYFormatted);

                    recipients.Add(new RockEmailMessageRecipient(person, mergeFields));

                    var emailMessage = new RockEmailMessage(systemCommunication);
                    emailMessage.SetRecipients(recipients);
                    emailMessage.Send(out List <string> emailErrors);

                    if (emailErrors.Any())
                    {
                        var errorLines = new StringBuilder();
                        errorLines.AppendLine(string.Empty);
                        foreach (string error in emailErrors)
                        {
                            errorLines.AppendLine(error);
                        }

                        // Provide better identifying context in case the errors are too vague.
                        var exception = new Exception($"Unable to send email (Person ID = {person.Id}).{errorLines}");

                        result.EmailSendExceptions.Add(exception);
                    }
                    else
                    {
                        result.NoticesSentCount++;
                    }

                    // Start workflow for this person
                    if (workflowType != null)
                    {
                        Dictionary <string, string> attributes = new Dictionary <string, string>();
                        attributes.Add("Person", scheduledTransactionInfo.AuthorizedPersonAliasGuid.ToString());
                        attributes.Add("Card", maskedCardNumber);
                        attributes.Add("Expiring", expirationDateMMYYFormatted);
                        attributes.Add("FinancialScheduledTransactionId", scheduledTransactionInfo.Id.ToString());

                        StartWorkflow(workflowService, workflowType, attributes, $"{person.FullName} (scheduled transaction Id: {scheduledTransactionInfo.Id})");
                    }
                }
            }

            return(result);
        }