Пример #1
0
        /// <summary>
        /// Resume a pending export: Checks if the export is complete. If the export is complete, then download the export, process the addresses and sent a notification.
        /// </summary>
        /// <param name="sparkDataConfig">The spark data configuration.</param>
        public void PendingExport(SparkDataConfig sparkDataConfig = null)
        {
            if (sparkDataConfig == null)
            {
                sparkDataConfig = GetSettings();
            }

            SparkDataApi.SparkDataApi sparkDataApi = new SparkDataApi.SparkDataApi();
            var credentials = sparkDataApi.NcoaGetCredentials(sparkDataConfig.SparkDataApiKey);

            var ncoaApi = new NcoaApi(credentials);

            if (!ncoaApi.IsReportExportCreated(sparkDataConfig.NcoaSettings.FileName))
            {
                return;
            }

            List <NcoaReturnRecord> ncoaReturnRecords;

            ncoaApi.DownloadExport(sparkDataConfig.NcoaSettings.CurrentReportExportKey, out ncoaReturnRecords);
            var ncoaHistoryList = ncoaReturnRecords.Select(r => r.ToNcoaHistory()).ToList();

            FilterDuplicateLocations(ncoaHistoryList);

            // Making sure that the database is empty to avoid adding duplicate data.
            using (var rockContext = new RockContext())
            {
                NcoaHistoryService ncoaHistoryService = new NcoaHistoryService(rockContext);
                ncoaHistoryService.DeleteRange(ncoaHistoryService.Queryable());
                rockContext.SaveChanges();
            }

            if (ncoaReturnRecords != null && ncoaReturnRecords.Count != 0)
            {
                using (var rockContext = new RockContext())
                {
                    var ncoaHistoryService = new NcoaHistoryService(rockContext);
                    ncoaHistoryService.AddRange(ncoaHistoryList);
                    rockContext.SaveChanges();
                }
            }

            ProcessNcoaResults(sparkDataConfig);

            sparkDataApi.NcoaCompleteReport(sparkDataConfig.SparkDataApiKey, sparkDataConfig.NcoaSettings.FileName, sparkDataConfig.NcoaSettings.CurrentReportExportKey);

            //Notify group
            SentNotification(sparkDataConfig, "finished");

            sparkDataConfig.NcoaSettings.LastRunDate         = RockDateTime.Now;
            sparkDataConfig.NcoaSettings.CurrentReportStatus = "Complete";
            sparkDataConfig.NcoaSettings.FileName            = null;
            SaveSettings(sparkDataConfig);
        }
Пример #2
0
        /// <summary>
        /// Job to get a National Change of Address (NCOA) report for all active people's addresses.
        ///
        /// Called by the <see cref="IScheduler" /> when a
        /// <see cref="ITrigger" /> fires that is associated with
        /// the <see cref="IJob" />.
        /// </summary>
        public virtual void Execute(IJobExecutionContext context)
        {
            Exception exception = null;
            // Get the job setting(s)
            JobDataMap      dataMap         = context.JobDetail.JobDataMap;
            SparkDataConfig sparkDataConfig = Ncoa.GetSettings();

            if (!sparkDataConfig.NcoaSettings.IsEnabled || !sparkDataConfig.NcoaSettings.IsValid())
            {
                return;
            }

            try
            {
                Guid?sparkDataApiKeyGuid = sparkDataConfig.SparkDataApiKey.AsGuidOrNull();
                if (sparkDataApiKeyGuid == null)
                {
                    exception = new Exception($"Spark Data Api Key '{sparkDataConfig.SparkDataApiKey.ToStringSafe()}' is empty or invalid. The Spark Data Api Key can be configured in System Settings > Spark Data Settings.");
                    return;
                }

                switch (sparkDataConfig.NcoaSettings.CurrentReportStatus)
                {
                case "":
                case null:
                    if (sparkDataConfig.NcoaSettings.RecurringEnabled)
                    {
                        StatusStart(sparkDataConfig);
                    }

                    break;

                case "Start":
                    StatusStart(sparkDataConfig);
                    break;

                case "Failed":
                    StatusFailed(sparkDataConfig);
                    break;

                case "Pending: Report":
                    StatusPendingReport(sparkDataConfig);
                    break;

                case "Pending: Export":
                    StatusPendingExport(sparkDataConfig);
                    break;

                case "Complete":
                    StatusComplete(sparkDataConfig);
                    break;
                }
            }
            catch (Exception ex)
            {
                exception = ex;
            }
            finally
            {
                if (exception != null)
                {
                    context.Result = $"NCOA Job failed: {exception.Message}";

                    sparkDataConfig.NcoaSettings.CurrentReportStatus = "Failed";
                    sparkDataConfig.Messages.Add($"NOCA job failed: {RockDateTime.Now.ToString()} - {exception.Message}");
                    Ncoa.SaveSettings(sparkDataConfig);

                    try
                    {
                        var ncoa = new Ncoa();
                        ncoa.SentNotification(sparkDataConfig, "failed");
                    }
                    catch
                    {
                    }


                    if (sparkDataConfig.SparkDataApiKey.IsNotNullOrWhiteSpace() && sparkDataConfig.NcoaSettings.FileName.IsNotNullOrWhiteSpace())
                    {
                        SparkDataApi sparkDataApi = new SparkDataApi();
                    }

                    Exception   ex       = new AggregateException("NCOA job failed.", exception);
                    HttpContext context2 = HttpContext.Current;
                    ExceptionLogService.LogException(ex, context2);
                    throw ex;
                }
                else
                {
                    string msg;
                    if (sparkDataConfig.NcoaSettings.CurrentReportStatus == "Complete")
                    {
                        using (RockContext rockContext = new RockContext())
                        {
                            NcoaHistoryService ncoaHistoryService = new NcoaHistoryService(rockContext);
                            msg = $"NCOA request processed, {ncoaHistoryService.Count()} {(ncoaHistoryService.Count() == 1 ? "address" : "addresses")} processed, {ncoaHistoryService.MovedCount()} {(ncoaHistoryService.MovedCount() > 1 ? "were" : "was")} marked as 'moved'";
                        }
                    }
                    else
                    {
                        msg = $"Job complete. NCOA status: {sparkDataConfig.NcoaSettings.CurrentReportStatus}";
                    }

                    context.Result = msg;
                    sparkDataConfig.Messages.Add($"{msg}: {RockDateTime.Now.ToString()}");
                    Ncoa.SaveSettings(sparkDataConfig);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Shows the view.
        /// </summary>
        protected void ShowView()
        {
            var rockContext = new RockContext();

            int resultCount = Int32.Parse(GetAttributeValue("ResultCount"));
            int pageNumber  = 0;

            if (!String.IsNullOrEmpty(PageParameter("page")))
            {
                pageNumber = Int32.Parse(PageParameter("page"));
            }

            var skipCount = pageNumber * resultCount;

            var query = new NcoaHistoryService(rockContext).Queryable();

            var processed = gfNcoaFilter.GetUserPreference("Processed").ConvertToEnumOrNull <Processed>();

            if (processed.HasValue)
            {
                if (processed.Value != Processed.All && processed.Value != Processed.ManualUpdateRequiredOrNotProcessed)
                {
                    query = query.Where(i => i.Processed == processed);
                }
                else if (processed.Value == Processed.ManualUpdateRequiredOrNotProcessed)
                {
                    query = query.Where(i => i.Processed == Processed.ManualUpdateRequired || i.Processed == Processed.NotProcessed);
                }
            }

            var moveDateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(gfNcoaFilter.GetUserPreference("Move Date"));

            if (moveDateRange.Start.HasValue)
            {
                query = query.Where(e => e.MoveDate.HasValue && e.MoveDate.Value >= moveDateRange.Start.Value);
            }
            if (moveDateRange.End.HasValue)
            {
                query = query.Where(e => e.MoveDate.HasValue && e.MoveDate.Value < moveDateRange.End.Value);
            }

            var ncoaDateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(gfNcoaFilter.GetUserPreference("NCOA Processed Date"));

            if (ncoaDateRange.Start.HasValue)
            {
                query = query.Where(e => e.NcoaRunDateTime >= ncoaDateRange.Start.Value);
            }
            if (ncoaDateRange.End.HasValue)
            {
                query = query.Where(e => e.NcoaRunDateTime < ncoaDateRange.End.Value);
            }

            var moveType = gfNcoaFilter.GetUserPreference("Move Type").ConvertToEnumOrNull <MoveType>();

            if (moveType.HasValue)
            {
                query = query.Where(i => i.MoveType == moveType);
            }

            var addressStatus = gfNcoaFilter.GetUserPreference("Address Status").ConvertToEnumOrNull <AddressStatus>();

            if (addressStatus.HasValue)
            {
                query = query.Where(i => i.AddressStatus == addressStatus);
            }

            var addressInvalidReason = gfNcoaFilter.GetUserPreference("Address Invalid Reason").ConvertToEnumOrNull <AddressInvalidReason>();

            if (addressInvalidReason.HasValue)
            {
                query = query.Where(i => i.AddressInvalidReason == addressInvalidReason);
            }

            decimal?moveDistance = gfNcoaFilter.GetUserPreference("Move Distance").AsDecimalOrNull();

            if (moveDistance.HasValue)
            {
                query = query.Where(i => i.MoveDistance <= moveDistance.Value);
            }

            string lastName = gfNcoaFilter.GetUserPreference("Last Name");

            if (!string.IsNullOrWhiteSpace(lastName))
            {
                var personAliasQuery = new PersonAliasService(rockContext)
                                       .Queryable()
                                       .Where(p =>
                                              p.Person != null &&
                                              p.Person.LastName.Contains(lastName))
                                       .Select(p => p.Id);
                query = query.Where(i => personAliasQuery.Contains(i.PersonAliasId));
            }

            var campusId = gfNcoaFilter.GetUserPreference("Campus").AsIntegerOrNull();

            if (campusId.HasValue)
            {
                var familyGroupType  = GroupTypeCache.Get(Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid());
                var personAliasQuery = new PersonAliasService(rockContext).Queryable().AsNoTracking();
                var campusQuery      = new GroupMemberService(rockContext)
                                       .Queryable().AsNoTracking()
                                       .Where(m =>
                                              m.Group.GroupTypeId == familyGroupType.Id &&
                                              m.Group.CampusId.HasValue &&
                                              m.Group.CampusId.Value == campusId.Value)
                                       .Select(m => m.PersonId)
                                       .Join(personAliasQuery, m => m, p => p.PersonId, (m, p) => p.Id);

                query = query.Where(i => campusQuery.Contains(i.PersonAliasId));
            }

            var filteredRecords = query.ToList();

            lTotal.Text = string.Format("Records: {0}", filteredRecords.Count());

            #region Grouping rows

            var ncoaRows = filteredRecords
                           .Where(a => a.MoveType != MoveType.Individual)
                           .GroupBy(a => new { a.FamilyId, a.MoveType, a.MoveDate })
                           .Select(a => new NcoaRow
            {
                Id = a.Select(b => b.Id).Max(),
                FamilyMemberPersonAliasIds = a.Select(b => b.PersonAliasId).ToList()
            }).ToList();

            var ncoaIndividualRows = filteredRecords
                                     .Where(a => a.MoveType == MoveType.Individual)
                                     .Select(a => new NcoaRow
            {
                Id = a.Id,
                IndividualPersonAliasId = a.PersonAliasId
            }).ToList();

            ncoaRows.AddRange(ncoaIndividualRows);

            #endregion

            var pagedNcoaRows = ncoaRows.OrderBy(a => a.Id).Skip(skipCount).Take(resultCount + 1).ToList();
            var familyMemberPersonAliasIds = pagedNcoaRows.SelectMany(r => r.FamilyMemberPersonAliasIds).ToList();
            var individualPersonAliasIds   = pagedNcoaRows.Select(r => r.IndividualPersonAliasId).ToList();

            var people = new PersonAliasService(rockContext)
                         .Queryable().AsNoTracking()
                         .Where(p =>
                                familyMemberPersonAliasIds.Contains(p.Id) ||
                                individualPersonAliasIds.Contains(p.Id))
                         .Select(p => new
            {
                PersonAliasId = p.Id,
                Person        = p.Person
            })
                         .ToList();

            foreach (var ncoaRow in pagedNcoaRows)
            {
                ncoaRow.FamilyMembers = people
                                        .Where(p => ncoaRow.FamilyMemberPersonAliasIds.Contains(p.PersonAliasId))
                                        .Select(p => p.Person)
                                        .ToList();

                ncoaRow.Individual = people
                                     .Where(p => p.PersonAliasId == ncoaRow.IndividualPersonAliasId)
                                     .Select(p => p.Person)
                                     .FirstOrDefault();

                var ncoaHistoryRecord = filteredRecords.Single(a => a.Id == ncoaRow.Id);

                ncoaRow.OriginalAddress = FormattedAddress(ncoaHistoryRecord.OriginalStreet1, ncoaHistoryRecord.OriginalStreet2,
                                                           ncoaHistoryRecord.OriginalCity, ncoaHistoryRecord.OriginalState, ncoaHistoryRecord.OriginalPostalCode)
                                          .ConvertCrLfToHtmlBr();
                ncoaRow.Status         = ncoaHistoryRecord.Processed == Processed.Complete ? "Processed" : "Not Processed";
                ncoaRow.StatusCssClass = ncoaHistoryRecord.Processed == Processed.Complete ? "label-success" : "label-default";
                ncoaRow.ShowButton     = false;

                var family = new GroupService(rockContext).Get(ncoaHistoryRecord.FamilyId);
                var person = ncoaRow.Individual ?? ncoaRow.FamilyMembers.First();
                if (family == null)
                {
                    family = person.GetFamily(rockContext);
                }

                var personService = new PersonService(rockContext);

                ncoaRow.FamilyName         = family.Name;
                ncoaRow.HeadOftheHousehold = personService.GetHeadOfHousehold(person, family);

                if (ncoaHistoryRecord.MoveType != MoveType.Individual)
                {
                    ncoaRow.FamilyMembers = personService.GetFamilyMembers(family, person.Id, true).Select(a => a.Person).ToList();
                }
                else
                {
                    ncoaRow.FamilyMembers = personService.GetFamilyMembers(family, person.Id, false).Select(a => a.Person).ToList();
                }

                if (ncoaHistoryRecord.AddressStatus == AddressStatus.Invalid)
                {
                    ncoaRow.TagLine         = "Invalid Address";
                    ncoaRow.TagLineCssClass = "label-warning";

                    if (ncoaHistoryRecord.Processed != Processed.Complete)
                    {
                        ncoaRow.CommandName = "MarkAddressAsPrevious";
                        ncoaRow.CommandText = "Mark Address As Previous";
                        ncoaRow.ShowButton  = true;
                    }
                }

                if (ncoaHistoryRecord.NcoaType == NcoaType.Month48Move)
                {
                    ncoaRow.TagLine         = "48 Month Move";
                    ncoaRow.TagLineCssClass = "label-info";

                    if (ncoaHistoryRecord.Processed != Processed.Complete)
                    {
                        ncoaRow.CommandName = "MarkAddressAsPrevious";
                        ncoaRow.CommandText = "Mark Address As Previous";
                        ncoaRow.ShowButton  = true;
                    }
                }

                if (ncoaHistoryRecord.NcoaType == NcoaType.Move)
                {
                    ncoaRow.TagLine         = ncoaHistoryRecord.MoveType.ConvertToString();
                    ncoaRow.TagLineCssClass = "label-success";
                    ncoaRow.MoveDate        = ncoaHistoryRecord.MoveDate;
                    ncoaRow.MoveDistance    = ncoaHistoryRecord.MoveDistance;
                    ncoaRow.NewAddress      = FormattedAddress(ncoaHistoryRecord.UpdatedStreet1, ncoaHistoryRecord.UpdatedStreet2,
                                                               ncoaHistoryRecord.UpdatedCity, ncoaHistoryRecord.UpdatedState, ncoaHistoryRecord.UpdatedPostalCode)
                                              .ConvertCrLfToHtmlBr();
                    if (ncoaHistoryRecord.Processed != Processed.Complete)
                    {
                        ncoaRow.CommandText = "Mark Processed";
                        ncoaRow.CommandName = "MarkProcessed";
                        ncoaRow.ShowButton  = true;
                    }
                }
            }

            rptNcoaResultsFamily.DataSource = pagedNcoaRows.Take(resultCount).GroupBy(n => n.FamilyName);
            rptNcoaResultsFamily.DataBind();

            if (pagedNcoaRows.Count() > resultCount)
            {
                hlNext.Visible = hlNext.Enabled = true;
                Dictionary <string, string> queryStringNext = new Dictionary <string, string>();
                queryStringNext.Add("page", (pageNumber + 1).ToString());
                var pageReferenceNext = new Rock.Web.PageReference(CurrentPageReference.PageId, CurrentPageReference.RouteId, queryStringNext);
                hlNext.NavigateUrl = pageReferenceNext.BuildUrl();
            }
            else
            {
                hlNext.Visible = hlNext.Enabled = false;
            }

            // build prev button
            if (pageNumber == 0)
            {
                hlPrev.Visible = hlPrev.Enabled = false;
            }
            else
            {
                hlPrev.Visible = hlPrev.Enabled = true;
                Dictionary <string, string> queryStringPrev = new Dictionary <string, string>();
                queryStringPrev.Add("page", (pageNumber - 1).ToString());
                var pageReferencePrev = new Rock.Web.PageReference(CurrentPageReference.PageId, CurrentPageReference.RouteId, queryStringPrev);
                hlPrev.NavigateUrl = pageReferencePrev.BuildUrl();
            }
        }
Пример #4
0
        /// <summary>
        /// Handles the ItemCommand event of the rptNcoaResults control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RepeaterCommandEventArgs"/> instance containing the event data.</param>
        protected void rptNcoaResults_ItemCommand(object sender, RepeaterCommandEventArgs e)
        {
            var ncoaHistoryId = e.CommandArgument.ToStringSafe().AsIntegerOrNull();

            if (!ncoaHistoryId.HasValue)
            {
                return;
            }

            if (e.CommandName == "MarkAddressAsPrevious")
            {
                using (var rockContext = new RockContext())
                {
                    var ncoaHistory = new NcoaHistoryService(rockContext).Get(ncoaHistoryId.Value);
                    if (ncoaHistory != null)
                    {
                        var groupService         = new GroupService(rockContext);
                        var groupLocationService = new GroupLocationService(rockContext);

                        var changes = new History.HistoryChangeList();

                        Ncoa ncoa                  = new Ncoa();
                        var  previousValue         = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_PREVIOUS.AsGuid());
                        int? previousValueId       = previousValue == null ? ( int? )null : previousValue.Id;
                        var  previousGroupLocation = ncoa.MarkAsPreviousLocation(ncoaHistory, groupLocationService, previousValueId, changes);
                        if (previousGroupLocation != null)
                        {
                            ncoaHistory.Processed = Processed.Complete;

                            // If there were any changes, write to history
                            if (changes.Any())
                            {
                                var family = groupService.Get(ncoaHistory.FamilyId);
                                if (family != null)
                                {
                                    foreach (var fm in family.Members)
                                    {
                                        HistoryService.SaveChanges(
                                            rockContext,
                                            typeof(Person),
                                            Rock.SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(),
                                            fm.PersonId,
                                            changes,
                                            family.Name,
                                            typeof(Group),
                                            family.Id,
                                            false);
                                    }
                                }
                            }
                        }
                    }

                    rockContext.SaveChanges();
                }
            }
            else if (e.CommandName == "MarkProcessed")
            {
                using (RockContext rockContext = new RockContext())
                {
                    var ncoa = (new NcoaHistoryService(rockContext)).Get(ncoaHistoryId.Value);
                    ncoa.Processed = Processed.Complete;
                    rockContext.SaveChanges();
                }
            }

            NcoaResults_BlockUpdated(null, null);
        }
Пример #5
0
        /// <summary>
        /// Processes the NCOA results: Mark all individual move addresses as previous, add the new address as current; and processed.
        /// If minMoveDistance is specified, mark the individual as inactive if the individual moved further than the specified distance.
        /// </summary>
        /// <param name="inactiveReason">The inactive reason.</param>
        /// <param name="minMoveDistance">The minimum move distance.</param>
        /// <param name="homeValueId">The home value identifier.</param>
        /// <param name="previousValueId">The previous value identifier.</param>
        private void ProcessNcoaResultsIndividualMove(DefinedValueCache inactiveReason, decimal?minMoveDistance, int?homeValueId, int?previousValueId)
        {
            List <int> ncoaIds = null;

            // Process 'Move' NCOA Types (For the remaining Individual move types that weren't updated with the family move)
            using (var rockContext = new RockContext())
            {
                ncoaIds = new NcoaHistoryService(rockContext)
                          .Queryable().AsNoTracking()
                          .Where(n =>
                                 n.Processed == Processed.NotProcessed &&
                                 n.NcoaType == NcoaType.Move &&
                                 n.MoveType == MoveType.Individual)
                          .Select(n => n.Id)
                          .ToList();
            }

            foreach (int id in ncoaIds)
            {
                using (var rockContext = new RockContext())
                {
                    // Get the NCOA record and make sure it still hasn't been processed
                    var ncoaHistory = new NcoaHistoryService(rockContext).Get(id);
                    if (ncoaHistory != null && ncoaHistory.Processed == Processed.NotProcessed)
                    {
                        var ncoaHistoryService   = new NcoaHistoryService(rockContext);
                        var groupMemberService   = new GroupMemberService(rockContext);
                        var personAliasService   = new PersonAliasService(rockContext);
                        var groupService         = new GroupService(rockContext);
                        var groupLocationService = new GroupLocationService(rockContext);
                        var locationService      = new LocationService(rockContext);
                        var personService        = new PersonService(rockContext);

                        var changes = new History.HistoryChangeList();

                        // Default the status to requiring a manual update (we might change this though)
                        ncoaHistory.Processed = Processed.ManualUpdateRequired;

                        // Find the existing family
                        var family = groupService.Get(ncoaHistory.FamilyId);

                        // If there's only one person in the family
                        if (family.Members.Count == 1)
                        {
                            // And that person is the same as the move record's person then we can process it.
                            var personAlias  = personAliasService.Get(ncoaHistory.PersonAliasId);
                            var familyMember = family.Members.First();
                            if (personAlias != null && familyMember.PersonId == personAlias.PersonId)
                            {
                                // If were able to mark their existing address as previous and add a new updated Home address,
                                // then set the status to complete (otherwise leave it as needing a manual update).
                                var previousGroupLocation = MarkAsPreviousLocation(ncoaHistory, groupLocationService, previousValueId, changes);
                                if (previousGroupLocation != null)
                                {
                                    if (AddNewHomeLocation(ncoaHistory, locationService, groupLocationService, homeValueId, changes, previousGroupLocation.IsMailingLocation, previousGroupLocation.IsMappedLocation))
                                    {
                                        ncoaHistory.Processed = Processed.Complete;

                                        // Look for any other moves for the same person to same address, and set their process to complete also
                                        foreach (var ncoaIndividual in ncoaHistoryService
                                                 .Queryable().Where(n =>
                                                                    n.Processed == Processed.NotProcessed &&
                                                                    n.NcoaType == NcoaType.Move &&
                                                                    n.MoveType == MoveType.Individual &&
                                                                    n.PersonAliasId == ncoaHistory.PersonAliasId &&
                                                                    n.Id != ncoaHistory.Id &&
                                                                    n.UpdatedStreet1 == ncoaHistory.UpdatedStreet1))
                                        {
                                            ncoaIndividual.Processed = Processed.Complete;
                                        }

                                        // If there were any changes, write to history and check to see if person should be inactivated
                                        if (changes.Any())
                                        {
                                            if (ncoaHistory.MoveDistance.HasValue && minMoveDistance.HasValue &&
                                                ncoaHistory.MoveDistance.Value >= minMoveDistance.Value)
                                            {
                                                History.HistoryChangeList personChanges;

                                                personService.InactivatePerson(familyMember.Person, inactiveReason,
                                                                               $"Received a Change of Address (NCOA) notice that was for more than {minMoveDistance} miles away.", out personChanges);

                                                if (personChanges.Any())
                                                {
                                                    HistoryService.SaveChanges(
                                                        rockContext,
                                                        typeof(Person),
                                                        SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                                                        familyMember.PersonId,
                                                        personChanges,
                                                        false);
                                                }
                                            }

                                            HistoryService.SaveChanges(
                                                rockContext,
                                                typeof(Person),
                                                SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(),
                                                familyMember.PersonId,
                                                changes,
                                                family.Name,
                                                typeof(Group),
                                                family.Id,
                                                false);
                                        }
                                    }
                                }
                            }
                        }

                        rockContext.SaveChanges();
                    }
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Processes the NCOA results: Mark all family move addresses as previous, add the new address as current; and processed.
        /// If minMoveDistance is specified, mark the family as inactive if the family moved further than the specified distance.
        /// </summary>
        /// <param name="inactiveReason">The inactive reason.</param>
        /// <param name="minMoveDistance">The minimum move distance.</param>
        /// <param name="homeValueId">The home value identifier.</param>
        /// <param name="previousValueId">The previous value identifier.</param>
        private void ProcessNcoaResultsFamilyMove(DefinedValueCache inactiveReason, decimal?minMoveDistance, int?homeValueId, int?previousValueId)
        {
            List <int> ncoaIds = null;

            // Process 'Move' NCOA Types (The 'Family' move types will be processed first)
            using (var rockContext = new RockContext())
            {
                ncoaIds = new NcoaHistoryService(rockContext)
                          .Queryable().AsNoTracking()
                          .Where(n =>
                                 n.Processed == Processed.NotProcessed &&
                                 n.NcoaType == NcoaType.Move &&
                                 n.MoveType == MoveType.Family)
                          .Select(n => n.Id)
                          .ToList();
            }

            foreach (int id in ncoaIds)
            {
                using (var rockContext = new RockContext())
                {
                    // Get the NCOA record and make sure it still hasn't been processed
                    var ncoaHistory = new NcoaHistoryService(rockContext).Get(id);
                    if (ncoaHistory != null && ncoaHistory.Processed == Processed.NotProcessed)
                    {
                        var ncoaHistoryService   = new NcoaHistoryService(rockContext);
                        var groupService         = new GroupService(rockContext);
                        var groupLocationService = new GroupLocationService(rockContext);
                        var locationService      = new LocationService(rockContext);
                        var personService        = new PersonService(rockContext);

                        var familyChanges = new History.HistoryChangeList();

                        ncoaHistory.Processed = Processed.ManualUpdateRequired;

                        // If we're able to mark the existing address as previous and successfully create a new home address..
                        var previousGroupLocation = MarkAsPreviousLocation(ncoaHistory, groupLocationService, previousValueId, familyChanges);
                        if (previousGroupLocation != null)
                        {
                            if (AddNewHomeLocation(ncoaHistory, locationService, groupLocationService, homeValueId, familyChanges, previousGroupLocation.IsMailingLocation, previousGroupLocation.IsMappedLocation))
                            {
                                // set the status to 'Complete'
                                ncoaHistory.Processed = Processed.Complete;

                                // Look for any other moves for the same family and to same address, and set their status to complete as well
                                foreach (var ncoaIndividual in ncoaHistoryService
                                         .Queryable().Where(n =>
                                                            n.Processed == Processed.NotProcessed &&
                                                            n.NcoaType == NcoaType.Move &&
                                                            n.FamilyId == ncoaHistory.FamilyId &&
                                                            n.Id != ncoaHistory.Id &&
                                                            n.UpdatedStreet1 == ncoaHistory.UpdatedStreet1))
                                {
                                    ncoaIndividual.Processed = Processed.Complete;
                                }

                                // If there were any changes, write to history and check to see if person should be inactivated
                                if (familyChanges.Any())
                                {
                                    var family = groupService.Get(ncoaHistory.FamilyId);
                                    if (family != null)
                                    {
                                        foreach (var fm in family.Members)
                                        {
                                            if (ncoaHistory.MoveDistance.HasValue && minMoveDistance.HasValue &&
                                                ncoaHistory.MoveDistance.Value >= minMoveDistance.Value)
                                            {
                                                History.HistoryChangeList personChanges;

                                                personService.InactivatePerson(fm.Person, inactiveReason,
                                                                               $"Received a Change of Address (NCOA) notice that was for more than {minMoveDistance} miles away.", out personChanges);

                                                if (personChanges.Any())
                                                {
                                                    HistoryService.SaveChanges(
                                                        rockContext,
                                                        typeof(Person),
                                                        SystemGuid.Category.HISTORY_PERSON_DEMOGRAPHIC_CHANGES.AsGuid(),
                                                        fm.PersonId,
                                                        personChanges,
                                                        false);
                                                }
                                            }

                                            HistoryService.SaveChanges(
                                                rockContext,
                                                typeof(Person),
                                                SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(),
                                                fm.PersonId,
                                                familyChanges,
                                                family.Name,
                                                typeof(Group),
                                                family.Id,
                                                false);
                                        }
                                    }
                                }
                            }
                        }

                        rockContext.SaveChanges();
                    }
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Processes the NCOA results: Mark all 48 month move addresses as previous and processed if enabled, otherwise mark as manual update required.
        /// </summary>
        /// <param name="mark48MonthAsPrevious">if a 48 month move should be marked as previous, set to <c>true</c>.</param>
        /// <param name="previousValueId">The previous value identifier.</param>
        private void ProcessNcoaResults48MonthMove(bool mark48MonthAsPrevious, int?previousValueId)
        {
            List <int> ncoaIds = null;

            // Process the '48 Month Move' NCOA Types
            using (var rockContext = new RockContext())
            {
                ncoaIds = new NcoaHistoryService(rockContext)
                          .Queryable().AsNoTracking()
                          .Where(n =>
                                 n.Processed == Processed.NotProcessed &&
                                 n.NcoaType == NcoaType.Month48Move)
                          .Select(n => n.Id)
                          .ToList();
            }

            foreach (int id in ncoaIds)
            {
                using (var rockContext = new RockContext())
                {
                    var ncoaHistory = new NcoaHistoryService(rockContext).Get(id);
                    if (ncoaHistory != null)
                    {
                        var groupService         = new GroupService(rockContext);
                        var groupLocationService = new GroupLocationService(rockContext);

                        var changes = new History.HistoryChangeList();

                        // If configured to mark these as previous, and we're able to mark it as previous set the status to 'Complete'
                        // otherwise set it to require a manual update
                        if (mark48MonthAsPrevious && MarkAsPreviousLocation(ncoaHistory, groupLocationService, previousValueId, changes) != null)
                        {
                            ncoaHistory.Processed = Processed.Complete;

                            // If there were any changes, write to history
                            if (changes.Any())
                            {
                                var family = groupService.Get(ncoaHistory.FamilyId);
                                if (family != null)
                                {
                                    foreach (var fm in family.Members)
                                    {
                                        HistoryService.SaveChanges(
                                            rockContext,
                                            typeof(Person),
                                            SystemGuid.Category.HISTORY_PERSON_FAMILY_CHANGES.AsGuid(),
                                            fm.PersonId,
                                            changes,
                                            family.Name,
                                            typeof(Group),
                                            family.Id,
                                            false);
                                    }
                                }
                            }
                        }
                        else
                        {
                            ncoaHistory.Processed = Processed.ManualUpdateRequired;
                        }

                        rockContext.SaveChanges();
                    }
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Starts the NCOA request: Check if there is a valid credit card on the Spark Data server. If there is a valid credit card, then get the addresses, initialize a report on NCOA, upload the addresses to NCOA and delete the previous NcoaHistory data.
        /// </summary>
        /// <param name="sparkDataConfig">The spark data configuration.</param>
        public void Start(SparkDataConfig sparkDataConfig)
        {
            if (sparkDataConfig == null)
            {
                sparkDataConfig = GetSettings();
            }

            SparkDataApi.SparkDataApi sparkDataApi = new SparkDataApi.SparkDataApi();
            var accountStatus = sparkDataApi.CheckAccount(sparkDataConfig.SparkDataApiKey);

            switch (accountStatus)
            {
            case SparkDataApi.SparkDataApi.AccountStatus.AccountNoName:
                throw new UnauthorizedAccessException("Account does not have a name.");

            case SparkDataApi.SparkDataApi.AccountStatus.AccountNotFound:
                throw new UnauthorizedAccessException("Account not found.");

            case SparkDataApi.SparkDataApi.AccountStatus.Disabled:
                throw new UnauthorizedAccessException("Account is disabled.");

            case SparkDataApi.SparkDataApi.AccountStatus.EnabledCardExpired:
                throw new UnauthorizedAccessException("Credit card on Spark server expired.");

            case SparkDataApi.SparkDataApi.AccountStatus.EnabledNoCard:
                throw new UnauthorizedAccessException("No credit card found on Spark server.");

            case SparkDataApi.SparkDataApi.AccountStatus.InvalidSparkDataKey:
                throw new UnauthorizedAccessException("Invalid Spark Data Key.");
            }

            var addresses = GetAddresses(sparkDataConfig.NcoaSettings.PersonDataViewId);

            if (addresses.Count == 0)
            {
                sparkDataConfig.NcoaSettings.LastRunDate         = RockDateTime.Now;
                sparkDataConfig.NcoaSettings.CurrentReportStatus = "Complete";
                SaveSettings(sparkDataConfig);
                return;
            }

            GroupNameTransactionKey groupNameTransactionKey = null;

            if (sparkDataConfig.NcoaSettings.FileName.IsNotNullOrWhiteSpace())
            {
                groupNameTransactionKey = sparkDataApi.NcoaRetryReport(sparkDataConfig.SparkDataApiKey, sparkDataConfig.NcoaSettings.FileName);
            }

            if (groupNameTransactionKey == null)
            {
                groupNameTransactionKey = sparkDataApi.NcoaInitiateReport(sparkDataConfig.SparkDataApiKey, addresses.Count, sparkDataConfig.NcoaSettings.PersonFullName);
            }

            if (groupNameTransactionKey == null)
            {
                if (sparkDataConfig.NcoaSettings.CurrentReportStatus == "Failed")
                {
                    // To avoid trying to charging customer over and over again...
                    sparkDataConfig.NcoaSettings.IsEnabled = false;
                }

                throw new Exception("Init NCOA: Failed to initialize request.");
            }

            sparkDataConfig.NcoaSettings.FileName = groupNameTransactionKey.TransactionKey;

            var credentials = sparkDataApi.NcoaGetCredentials(sparkDataConfig.SparkDataApiKey);
            var ncoaApi     = new NcoaApi(credentials);

            string id;

            ncoaApi.CreateFile(sparkDataConfig.NcoaSettings.FileName, groupNameTransactionKey.GroupName, out id);
            sparkDataConfig.NcoaSettings.CurrentReportKey = id;

            ncoaApi.UploadAddresses(addresses, sparkDataConfig.NcoaSettings.CurrentReportKey);

            sparkDataConfig.NcoaSettings.CurrentUploadCount = addresses.Count;
            ncoaApi.CreateReport(sparkDataConfig.NcoaSettings.CurrentReportKey);

            // Delete previous NcoaHistory entries. This prevent an user thinking the previous run's data is the current run's data.
            using (RockContext rockContext = new RockContext())
            {
                NcoaHistoryService ncoaHistoryService = new NcoaHistoryService(rockContext);
                ncoaHistoryService.DeleteRange(ncoaHistoryService.Queryable());
                rockContext.SaveChanges();
            }

            sparkDataConfig.NcoaSettings.CurrentReportStatus = "Pending: Report";
            SaveSettings(sparkDataConfig);
        }