Exemple #1
0
        /// <summary>
        /// Updates the Connection Requests to us the new To person
        /// </summary>
        protected void UpdateConnectionRequests()
        {
            //Get the selected people
            FromPersonId = ppFrom.PersonId;
            ToPersonId   = ppTo.PersonId;

            // Create Needed Services
            ConnectionRequestService connectionRequestService = new ConnectionRequestService(rockContext);

            //Get Connection Requests from From person
            var assigned = connectionRequestService.Queryable().Where(a => a.ConnectorPersonAliasId == FromPersonId);

            //Set each Connection Request in From person to To person
            foreach (var x in assigned)
            {
                x.ConnectorPersonAliasId  = ToPersonId;
                x.ModifiedDateTime        = DateTime.Now;
                x.ModifiedByPersonAliasId = CurrentPersonAliasId;
            }

            //Save changes
            rockContext.SaveChanges();

            //Update UI
            nbSuccess.Visible = true;
        }
Exemple #2
0
        /// <summary>
        /// Creates a Linq Expression that can be applied to an IQueryable to filter the result set.
        /// </summary>
        /// <param name="entityType">The type of entity in the result set.</param>
        /// <param name="serviceInstance">A service instance that can be queried to obtain the result set.</param>
        /// <param name="parameterExpression">The input parameter that will be injected into the filter expression.</param>
        /// <param name="selection">A formatted string representing the filter settings.</param>
        /// <returns>
        /// A Linq Expression that can be used to filter an IQueryable.
        /// </returns>
        /// <exception cref="System.Exception">Filter issue(s):  + errorMessages.AsDelimited( ;  )</exception>
        public override Expression GetExpression(Type entityType, IService serviceInstance, ParameterExpression parameterExpression, string selection)
        {
            var settings = new FilterSettings(selection);

            var context = ( RockContext )serviceInstance.Context;

            // Get the Connection Request Data View.
            var dataView = DataComponentSettingsHelper.GetDataViewForFilterComponent(settings.DataViewGuid, context);

            // Evaluate the Data View that defines the Person's Connection Request.
            var connectionRequestService = new ConnectionRequestService(context);

            var connectionRequestQuery = connectionRequestService.Queryable();

            if (dataView != null)
            {
                connectionRequestQuery = DataComponentSettingsHelper.FilterByDataView(connectionRequestQuery, dataView, connectionRequestService);
            }

            var connectionRequestPersonsKey = connectionRequestQuery.Select(a => a.PersonAliasId);
            // Get all of the Person corresponding to the qualifying Benevolence Requests.
            var qry = new PersonService(context).Queryable()
                      .Where(g => g.Aliases.Any(k => connectionRequestPersonsKey.Contains(k.Id)));

            // Retrieve the Filter Expression.
            var extractedFilterExpression = FilterExpressionExtractor.Extract <Model.Person>(qry, parameterExpression, "g");

            return(extractedFilterExpression);
        }
        public void ConnectionRequestDateKeyJoinsCorrectly()
        {
            var expectedRecordCount = 15;
            var year = 2015;

            using (var rockContext = new RockContext())
            {
                var connectionRequestService = new ConnectionRequestService(rockContext);

                var minDateValue = TestDataHelper.GetAnalyticsSourceMinDateForYear(rockContext, year);
                var maxDateValue = TestDataHelper.GetAnalyticsSourceMaxDateForYear(rockContext, year);

                for (var i = 0; i < 15; i++)
                {
                    var connectionRequest = BuildConnectionRequest(rockContext,
                                                                   TestDataHelper.GetRandomDateInRange(minDateValue, maxDateValue));

                    connectionRequestService.Add(connectionRequest);
                }

                rockContext.SaveChanges();
            }

            using (var rockContext = new RockContext())
            {
                var connectionRequestService = new ConnectionRequestService(rockContext);
                var connectionRequests       = connectionRequestService.
                                               Queryable().
                                               Where(i => i.ForeignKey == connectionRequestForeignKey).
                                               Where(i => i.CreatedSourceDate.CalendarYear == year);

                Assert.AreEqual(expectedRecordCount, connectionRequests.Count());
                Assert.IsNotNull(connectionRequests.First().CreatedSourceDate);
            }
        }
Exemple #4
0
        /// <summary>
        /// Handles the ItemDataBound event of the rConnectionTypes control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RepeaterItemEventArgs"/> instance containing the event data.</param>
        protected void rConnectionTypes_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            var lConnectionOpportunityList = e.Item.FindControl("lConnectionOpportunityList") as Literal;

            if (lConnectionOpportunityList != null)
            {
                var           connectionType = e.Item.DataItem as ConnectionType;
                var           pageGuid       = this.GetAttributeValue("ConnectionRequestDetail").AsGuidOrNull();
                PageReference connectionRequestDetailPage = null;
                if (pageGuid.HasValue)
                {
                    connectionRequestDetailPage = new PageReference(pageGuid.Value.ToString());
                }

                if (connectionType != null && this.Person != null)
                {
                    using (var rockContext = new RockContext())
                    {
                        int    personId = this.Person.Id;
                        var    connectionRequestService = new ConnectionRequestService(rockContext);
                        var    connectionRequestList    = connectionRequestService.Queryable().Where(a => a.PersonAlias.PersonId == personId && a.ConnectionOpportunity.ConnectionTypeId == connectionType.Id).OrderBy(a => a.ConnectionOpportunity.Name).AsNoTracking().ToList();
                        string listHtml = string.Empty;
                        foreach (var connectionRequest in connectionRequestList)
                        {
                            string connectionNameHtml;
                            string connectionName;
                            if (connectionRequest.CampusId.HasValue)
                            {
                                connectionName = string.Format("{0} ({1})", connectionRequest.ConnectionOpportunity, CampusCache.Read(connectionRequest.CampusId.Value));
                            }
                            else
                            {
                                connectionName = string.Format("{0}", connectionRequest.ConnectionOpportunity);
                            }

                            if (connectionRequestDetailPage != null && connectionRequestDetailPage.PageId > 0)
                            {
                                connectionRequestDetailPage.Parameters = new System.Collections.Generic.Dictionary <string, string>();
                                connectionRequestDetailPage.Parameters.Add("ConnectionRequestId", connectionRequest.Id.ToString());
                                connectionRequestDetailPage.Parameters.Add("ConnectionOpportunityId", connectionRequest.ConnectionOpportunityId.ToString());

                                connectionNameHtml = string.Format("<a href='{0}'>{1}</a>", connectionRequestDetailPage.BuildUrl(), connectionName);
                            }
                            else
                            {
                                connectionNameHtml = connectionName;
                            }

                            listHtml += string.Format(
                                "<li {0}>{1} - <small>{2}</small></li>",
                                (connectionRequest.ConnectionState == ConnectionState.Connected || connectionRequest.ConnectionState == ConnectionState.Inactive) ? "class='is-inactive'" : string.Empty,
                                connectionNameHtml,
                                connectionRequest.ConnectionState == ConnectionState.Connected ? "Connected" : connectionRequest.ConnectionStatus.ToString());
                        }

                        lConnectionOpportunityList.Text = listHtml;
                    }
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Get the connector based on entity Item and campaign configuration.
        /// </summary>
        /// <param name="campaignItem">The campaign item.</param>
        /// <param name="connectionOpportunity">The connection opportunity.</param>
        /// <param name="eligibleConnectors">The eligible connectors.</param>
        /// <param name="entityItemPersonAlias">The entity set item person alias.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <returns></returns>
        private int?GetConnector(CampaignItem campaignItem, ConnectionOpportunity connectionOpportunity, List <ConnectionConnector> eligibleConnectors, PersonAlias entityItemPersonAlias, RockContext rockContext)
        {
            int?connectorPersonId        = null;
            var dayofWeek                = RockDateTime.Now.DayOfWeek;
            var connectionRequestService = new ConnectionRequestService(rockContext);

            var defaultCampus = entityItemPersonAlias.Person.GetCampus();

            if (campaignItem.PreferPreviousConnector)
            {
                var personIds = eligibleConnectors
                                .Where(a => a.Limit - a.Current > 0 &&
                                       (!a.DaysOfWeek.Any() || a.DaysOfWeek.Contains(dayofWeek)) &&
                                       (!a.CampusId.HasValue || (a.CampusId.HasValue && defaultCampus != null && defaultCampus.Id == a.CampusId.Value)))
                                .Select(a => a.PersonId)
                                .ToList();

                if (personIds.Any())
                {
                    var person = connectionRequestService
                                 .Queryable()
                                 .Where(a => a.ConnectionOpportunityId == connectionOpportunity.Id &&
                                        a.PersonAlias.PersonId == entityItemPersonAlias.PersonId &&
                                        a.ConnectionState == ConnectionState.Connected &&
                                        a.ConnectorPersonAliasId.HasValue &&
                                        personIds.Contains(a.ConnectorPersonAlias.PersonId) &&
                                        a.ModifiedDateTime.HasValue)
                                 .OrderByDescending(a => a.ModifiedDateTime)
                                 .Select(a => a.ConnectorPersonAlias.Person)
                                 .FirstOrDefault();

                    if (person != null)
                    {
                        connectorPersonId = person.Id;
                    }
                }
            }

            if (!connectorPersonId.HasValue)
            {
                var eligibleConnector = eligibleConnectors
                                        .Where(a => a.Limit - a.Current > 0 &&
                                               (!a.DaysOfWeek.Any() || a.DaysOfWeek.Contains(dayofWeek)) &&
                                               (!a.CampusId.HasValue || (a.CampusId.HasValue && defaultCampus != null && defaultCampus.Id == a.CampusId.Value)))
                                        .OrderBy(a => a.Current)     // order from least assigned to most assigned
                                        .ThenBy(x => Guid.NewGuid()) // and then randomize
                                        .FirstOrDefault();

                if (eligibleConnector != null)
                {
                    connectorPersonId = eligibleConnector.PersonId;
                }
            }

            return(connectorPersonId);
        }
Exemple #6
0
        /// <summary>
        /// Gets both the opportunity request counts (TotalCount and AssignedToYouCount) for the
        /// given opportunities. The Person the service was initialized with is used to calculate
        /// <see cref="ConnectionRequestCountsViewModel.AssignedToYouCount"/>.
        /// </summary>
        /// <remarks>This method does not check security, it is assumed you have already done so.</remarks>
        /// <param name="connectionOpportunityIds">The connection opportunity identifiers.</param>
        /// <returns>A dictionary of connection request count objects.</returns>
        public Dictionary <int, ConnectionRequestCountsViewModel> GetOpportunityRequestCounts(IEnumerable <int> connectionOpportunityIds)
        {
            var connectionRequestService = new ConnectionRequestService(RockContext);

            // Create all counts as initially empty, this method must always return
            // a value for each opportunity id.
            var requestCounts = connectionOpportunityIds.ToDictionary(id => id, _ => new ConnectionRequestCountsViewModel());

            // Find all the connection requests assigned to the person.
            var activeConnectionRequestQry = connectionRequestService.Queryable()
                                             .Where(r => connectionOpportunityIds.Contains(r.ConnectionOpportunityId) &&
                                                    r.ConnectionState == ConnectionState.Active);

            // Group them by the connection opportunity and get the counts for
            // each opportunity.
            if (Person != null)
            {
                // If we have a Person (Person.Id) count their requests into the AssignedToYouCount along with the TotalCount.
                activeConnectionRequestQry
                .GroupBy(r => r.ConnectionOpportunityId)
                .Select(g => new
                {
                    Id         = g.Key,
                    Count      = g.Count(r => r.ConnectorPersonAliasId.HasValue && r.ConnectorPersonAlias.PersonId == Person.Id),
                    TotalCount = g.Count()
                })
                .ToList()
                .ForEach(o => { requestCounts[o.Id].AssignedToYouCount = o.Count; requestCounts[o.Id].TotalCount = o.TotalCount; });
            }
            else
            {
                // Otherwise, we can only count the total into the TotalCount.
                activeConnectionRequestQry
                .GroupBy(r => r.ConnectionOpportunityId)
                .Select(g => new
                {
                    Id         = g.Key,
                    TotalCount = g.Count()
                })
                .ToList()
                .ForEach(o => requestCounts[o.Id].TotalCount = o.TotalCount);
            }

            return(requestCounts);
        }
Exemple #7
0
        /// <summary>
        /// Gets any (active or past due FutureFollowUp) connection requests that don't have a connector
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="selectedCampaignItem">The selected campaign item.</param>
        /// <param name="connectorPerson">The connector person.</param>
        /// <returns></returns>
        public static IQueryable <ConnectionRequest> GetConnectionRequestsWithoutConnectorQuery(RockContext rockContext, CampaignItem selectedCampaignItem, Person connectorPerson)
        {
            var connectionRequestService = new ConnectionRequestService(rockContext);
            var currentDate = RockDateTime.Today;

            var connectorCampusIds = GetConnectorCampusIds(selectedCampaignItem, connectorPerson);

            // first, get any (active or past due FutureFollowUp) connection requests that don't have a connector
            var connectionRequestsWithoutConnectorQuery = connectionRequestService.Queryable()
                                                          .Where(a => a.ConnectionOpportunity.Guid == selectedCampaignItem.OpportunityGuid &&
                                                                 a.ConnectorPersonAliasId == null &&
                                                                 (a.ConnectionState == ConnectionState.Active || (a.ConnectionState == ConnectionState.FutureFollowUp && a.FollowupDate < currentDate)))

                                                          // only include pending connection requests that have a null campus, or the campus matches the connector's campus
                                                          .Where(a => (a.CampusId == null) || connectorCampusIds.Any(connectorCampusId => connectorCampusId == null || a.CampusId.Value == connectorCampusId));

            return(connectionRequestsWithoutConnectorQuery);
        }
        /// <summary>
        /// Get's all of the (get connected/ follow up) *requests* for a given person
        /// </summary>
        /// <param name="currentPerson">The leader</param>
        /// <returns></returns>
        public static IQueryable <ConnectionRequest> GetPeopleInLineFollowUpRequests(Person currentPerson)
        {
            if (currentPerson == null)
            {
                return(new List <ConnectionRequest>().AsQueryable());
            }

            var rockContext = new RockContext();

            var connectionRequestService  = new ConnectionRequestService(rockContext);
            int getConnectedOpportunityId =
                new ConnectionOpportunityService(rockContext).Get(
                    SystemGuid.ConnectionOpportunity.GET_CONNECTED.AsGuid()).Id;
            var connectionRequests = connectionRequestService
                                     .Queryable()
                                     .Where(c => c.ConnectionOpportunityId == getConnectedOpportunityId && c.ConnectorPersonAliasId == currentPerson.PrimaryAliasId && c.ConnectionState == ConnectionState.Active);


            return(connectionRequests);
        }
Exemple #9
0
        /// <summary>
        /// Gets the opportunity request counts for the given opportunities. The
        /// Person the service was initialized with is used to calculate
        /// <see cref="ConnectionRequestCountsViewModel.AssignedToYouCount"/>.
        /// </summary>
        /// <remarks>This method does not check security, it is assumed you have already done so.</remarks>
        /// <param name="connectionOpportunityIds">The connection opportunity identifiers.</param>
        /// <returns>A dictionary of connection request count objects.</returns>
        public Dictionary <int, ConnectionRequestCountsViewModel> GetOpportunityRequestCounts(IEnumerable <int> connectionOpportunityIds)
        {
            var connectionRequestService = new ConnectionRequestService(RockContext);

            // Create all counts as initially empty, this method must always return
            // a value for each opportunity id.
            var requestCounts = connectionOpportunityIds.ToDictionary(id => id, _ => new ConnectionRequestCountsViewModel());

            // Fast out, if there is no logged in person then just return a
            // bunch of zeros for now. Later if we add other counts we might
            // need more complex logic.
            if (Person == null)
            {
                return(requestCounts);
            }

            // Find all the connection requests assigned to the person.
            var assignedToYouRequestQry = connectionRequestService.Queryable()
                                          .Where(r => connectionOpportunityIds.Contains(r.ConnectionOpportunityId) &&
                                                 r.ConnectionState == ConnectionState.Active &&
                                                 r.ConnectorPersonAliasId.HasValue &&
                                                 r.ConnectorPersonAlias.PersonId == Person.Id);

            // Group them by the connection opportunity and get the counts for
            // each opportunity.
            assignedToYouRequestQry
            .GroupBy(r => r.ConnectionOpportunityId)
            .Select(g => new
            {
                Id    = g.Key,
                Count = g.Count()
            })
            .ToList()
            .ForEach(o => requestCounts[o.Id].AssignedToYouCount = o.Count);

            return(requestCounts);
        }
        public void Execute(IJobExecutionContext context)
        {
            JobDataMap dataMap     = context.JobDetail.JobDataMap;
            var        rockContext = new RockContext();

            var connectionOpportunities = dataMap.GetString("ConnectionOpportunities").SplitDelimitedValues();
            var systemEmail             = dataMap.GetString("Email").AsGuidOrNull();

            if (!systemEmail.HasValue)
            {
                throw new Exception("System Email is required!");
            }


            // get job type id
            int jobId      = Convert.ToInt16(context.JobDetail.Description);
            var jobService = new ServiceJobService(rockContext);
            var job        = jobService.Get(jobId);

            DateTime _midnightToday  = RockDateTime.Today.AddDays(1);
            var      currentDateTime = RockDateTime.Now;
            var      recipients      = new List <RockEmailMessageRecipient>();
            ConnectionRequestService connectionRequestService = new ConnectionRequestService(rockContext);
            PersonService            personService            = new PersonService(rockContext);
            var connectionRequestsQry = connectionRequestService.Queryable().Where(cr =>
                                                                                   connectionOpportunities.Contains(cr.ConnectionOpportunity.Guid.ToString()) &&
                                                                                   cr.ConnectorPersonAliasId != null &&
                                                                                   (
                                                                                       cr.ConnectionState == ConnectionState.Active ||
                                                                                       (cr.ConnectionState == ConnectionState.FutureFollowUp && cr.FollowupDate.HasValue && cr.FollowupDate.Value < _midnightToday)
                                                                                   ));


            var connectionRequestGroups = connectionRequestsQry.GroupBy(cr => cr.ConnectorPersonAlias.PersonId);

            foreach (var group in connectionRequestGroups)
            {
                Person person = personService.Get(group.Key);
                List <ConnectionOpportunity> opportunities = group.Select(a => a.ConnectionOpportunity).Distinct().ToList();
                var newConnectionRequests = group.Where(cr => cr.CreatedDateTime >= job.LastRunDateTime).GroupBy(cr => cr.ConnectionOpportunityId).ToList();
                // Get all the idle connections
                var idleConnectionRequests = group
                                             .Where(cr => (
                                                        (cr.ConnectionRequestActivities.Any() && cr.ConnectionRequestActivities.Max(ra => ra.CreatedDateTime) < currentDateTime.AddDays(-cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle))) ||
                                                    (!cr.ConnectionRequestActivities.Any() && cr.CreatedDateTime < currentDateTime.AddDays(-cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle))
                                                    )
                                             .Select(a => new { ConnectionOpportunityId = a.ConnectionOpportunityId, Id = a.Id })
                                             .GroupBy(cr => cr.ConnectionOpportunityId).ToList();

                // get list of requests that have a status that is considered critical.
                var criticalConnectionRequests = group
                                                 .Where(r =>
                                                        r.ConnectionStatus.IsCritical
                                                        )
                                                 .Select(a => new { ConnectionOpportunityId = a.ConnectionOpportunityId, Id = a.Id })
                                                 .GroupBy(cr => cr.ConnectionOpportunityId).ToList();

                var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null);
                mergeFields.Add("ConnectionOpportunities", opportunities);
                mergeFields.Add("ConnectionRequests", group.GroupBy(cr => cr.ConnectionOpportunity).ToList());
                mergeFields.Add("NewConnectionRequests", newConnectionRequests);
                mergeFields.Add("IdleConnectionRequestIds", idleConnectionRequests);
                mergeFields.Add("CriticalConnectionRequestIds", criticalConnectionRequests);
                mergeFields.Add("Person", person);
                mergeFields.Add("LastRunDate", job.LastRunDateTime);


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

            var emailMessage = new RockEmailMessage(systemEmail.Value);

            emailMessage.SetRecipients(recipients);
            emailMessage.CreateCommunicationRecord = dataMap.GetString("SaveCommunicationHistory").AsBoolean();
            emailMessage.Send();

            context.Result = string.Format("Sent " + recipients.Count + " connection digest emails.");
        }
Exemple #11
0
        /// <summary>
        /// Deletes the family's addresses, phone numbers, photos, viewed records, and people.
        /// TODO: delete attendance codes for attendance data that's about to be deleted when
        /// we delete the person record.
        /// </summary>
        /// <param name="families">The families.</param>
        /// <param name="rockContext">The rock context.</param>
        private void DeleteExistingFamilyData( XElement families, RockContext rockContext )
        {
            PersonService personService = new PersonService( rockContext );
            PhoneNumberService phoneNumberService = new PhoneNumberService( rockContext );
            PersonViewedService personViewedService = new PersonViewedService( rockContext );
            PageViewService pageViewService = new PageViewService( rockContext );
            BinaryFileService binaryFileService = new BinaryFileService( rockContext );
            PersonAliasService personAliasService = new PersonAliasService( rockContext );
            PersonDuplicateService personDuplicateService = new PersonDuplicateService( rockContext );
            NoteService noteService = new NoteService( rockContext );
            AuthService authService = new AuthService( rockContext );
            CommunicationService communicationService = new CommunicationService( rockContext );
            CommunicationRecipientService communicationRecipientService = new CommunicationRecipientService( rockContext );
            FinancialBatchService financialBatchService = new FinancialBatchService( rockContext );
            FinancialTransactionService financialTransactionService = new FinancialTransactionService( rockContext );
            PersonPreviousNameService personPreviousNameService = new PersonPreviousNameService( rockContext );
            ConnectionRequestService connectionRequestService = new ConnectionRequestService( rockContext );
            ConnectionRequestActivityService connectionRequestActivityService = new ConnectionRequestActivityService( rockContext );

            // delete the batch data
            List<int> imageIds = new List<int>();
            foreach ( var batch in financialBatchService.Queryable().Where( b => b.Name.StartsWith( "SampleData" ) ) )
            {
                imageIds.AddRange( batch.Transactions.SelectMany( t => t.Images ).Select( i => i.BinaryFileId ).ToList() );
                financialTransactionService.DeleteRange( batch.Transactions );
                financialBatchService.Delete( batch );
            }

            // delete all transaction images
            foreach ( var image in binaryFileService.GetByIds( imageIds ) )
            {
                binaryFileService.Delete( image );
            }

            foreach ( var elemFamily in families.Elements( "family" ) )
            {
                Guid guid = elemFamily.Attribute( "guid" ).Value.Trim().AsGuid();

                GroupService groupService = new GroupService( rockContext );
                Group family = groupService.Get( guid );
                if ( family != null )
                {
                    var groupMemberService = new GroupMemberService( rockContext );
                    var members = groupMemberService.GetByGroupId( family.Id, true );

                    // delete the people records
                    string errorMessage;
                    List<int> photoIds = members.Select( m => m.Person ).Where( p => p.PhotoId != null ).Select( a => (int)a.PhotoId ).ToList();

                    foreach ( var person in members.Select( m => m.Person ) )
                    {
                        person.GivingGroup = null;
                        person.GivingGroupId = null;
                        person.PhotoId = null;

                        // delete phone numbers
                        foreach ( var phone in phoneNumberService.GetByPersonId( person.Id ) )
                        {
                            if ( phone != null )
                            {
                                phoneNumberService.Delete( phone );
                            }
                        }

                        // delete communication recipient
                        foreach ( var recipient in communicationRecipientService.Queryable().Where( r => r.PersonAlias.PersonId == person.Id ) )
                        {
                            communicationRecipientService.Delete( recipient );
                        }

                        // delete communication
                        foreach ( var communication in communicationService.Queryable().Where( c => c.SenderPersonAliasId == person.PrimaryAlias.Id ) )
                        {
                            communicationService.Delete( communication );
                        }

                        // delete person viewed records
                        foreach ( var view in personViewedService.GetByTargetPersonId( person.Id ) )
                        {
                            personViewedService.Delete( view );
                        }

                        // delete page viewed records
                        foreach ( var view in pageViewService.GetByPersonId( person.Id ) )
                        {
                            pageViewService.Delete( view );
                        }

                        // delete notes created by them or on their record.
                        foreach ( var note in noteService.Queryable().Where ( n => n.CreatedByPersonAlias.PersonId == person.Id
                            || (n.NoteType.EntityTypeId == _personEntityTypeId && n.EntityId == person.Id ) ) )
                        {
                            noteService.Delete( note );
                        }

                        // delete previous names on their records
                        foreach ( var previousName in personPreviousNameService.Queryable().Where( r => r.PersonAlias.PersonId == person.Id ) )
                        {
                            personPreviousNameService.Delete( previousName );
                        }

                        // delete any GroupMember records they have
                        foreach ( var groupMember in groupMemberService.Queryable().Where( gm => gm.PersonId == person.Id ) )
                        {
                            groupMemberService.Delete( groupMember );
                        }

                        //// delete any Authorization data
                        //foreach ( var auth in authService.Queryable().Where( a => a.PersonId == person.Id ) )
                        //{
                        //    authService.Delete( auth );
                        //}

                        // delete their aliases
                        foreach ( var alias in personAliasService.Queryable().Where( a => a.PersonId == person.Id ) )
                        {
                            foreach ( var duplicate in personDuplicateService.Queryable().Where( d => d.DuplicatePersonAliasId == alias.Id ) )
                            {
                                personDuplicateService.Delete( duplicate );
                            }

                            personAliasService.Delete( alias );
                        }

                        // delete any connection requests tied to them
                        foreach ( var request in connectionRequestService.Queryable().Where( r => r.PersonAlias.PersonId == person.Id || r.ConnectorPersonAlias.PersonId == person.Id ) )
                        {
                            connectionRequestActivityService.DeleteRange( request.ConnectionRequestActivities );
                            connectionRequestService.Delete( request );
                        }

                        // Save these changes so the CanDelete passes the check...
                        //rockContext.ChangeTracker.DetectChanges();
                        rockContext.SaveChanges( disablePrePostProcessing: true );

                        if ( personService.CanDelete( person, out errorMessage ) )
                        {
                            personService.Delete( person );
                            //rockContext.ChangeTracker.DetectChanges();
                            //rockContext.SaveChanges( disablePrePostProcessing: true );
                        }
                        else
                        {
                            throw new Exception( string.Format( "Trying to delete {0}, but: {1}", person.FullName, errorMessage ) );
                        }
                    }

                    //rockContext.ChangeTracker.DetectChanges();
                    rockContext.SaveChanges( disablePrePostProcessing: true );

                    // delete all member photos
                    foreach ( var photo in binaryFileService.GetByIds( photoIds ) )
                    {
                        binaryFileService.Delete( photo );
                    }

                    DeleteGroupAndMemberData( family, rockContext );
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Returns the number of Workflows and Connection Requests for the selected Fron person, then populates grids.
        /// </summary>
        protected void UpdateUi()
        {
            // Get the selected person
            FromPersonId = ppFrom.PersonId;

            // Construct List
            var workflowResultList          = new List <WorkflowActivity>();
            var connectionRequestResultList = new List <ConnectionRequest>();

            // Create Needed Services
            WorkflowActivityService  workflowActivityService  = new WorkflowActivityService(rockContext);
            ConnectionRequestService connectionRequestService = new ConnectionRequestService(rockContext);

            // Get Workflows from From person
            var assignedWorkflows =
                workflowActivityService.Queryable()
                .Where(
                    a =>
                    a.AssignedPersonAliasId == FromPersonId && a.CompletedDateTime == null &&
                    a.Workflow.CompletedDateTime == null);


            // Get Connection Requests from From person
            var assignedConnectionRequests =
                connectionRequestService.Queryable()
                .Where(
                    b =>
                    b.ConnectorPersonAliasId == FromPersonId && b.ConnectionState != ConnectionState.Connected &&
                    b.ConnectionState != ConnectionState.Inactive);

            // UI Updates
            if (ppFrom.PersonId != null)
            {
                foreach (var workflow in assignedWorkflows)
                {
                    workflowResultList.Add(workflow);
                }

                foreach (var connectionRequest in assignedConnectionRequests)
                {
                    connectionRequestResultList.Add(connectionRequest);
                }


                lbCount.Text = assignedWorkflows.Count() + " open workflows assigned to this person.<br />" +
                               assignedConnectionRequests.Count() + " open Connection Requests assigned to this person.";

                gWorkflows.DataSource = workflowResultList;
                gWorkflows.DataBind();

                gConnections.DataSource = connectionRequestResultList;
                gConnections.DataBind();



                if (assignedWorkflows.Any())
                {
                    btnSaveWorkflows.Visible = true;
                    ppTo.Visible             = true;
                }

                if (assignedConnectionRequests.Any())
                {
                    btnSaveConnections.Visible = true;
                    ppTo.Visible = true;
                }
            }

            else
            {
                nbSuccess.Visible        = false;
                nbWarningMessage.Visible = false;
            }
        }
        /// <summary>
        /// Processes the connection type.
        /// </summary>
        /// <param name="connectionTypeView">The connection type view.</param>
        /// <param name="updatedResults">The updated results.</param>
        /// <param name="errorMessages">The error message.</param>
        private void ProcessConnectionType(
            ConnectionTypeView connectionTypeView,
            ConcurrentBag <int> updatedResults,
            out List <string> errorMessages)
        {
            errorMessages = new List <string>();
            var groupViews = new List <GroupView>();

            foreach (var connectionStatus in connectionTypeView.ConnectionStatuses)
            {
                foreach (var connectionStatusAutomation in connectionStatus.ConnectionStatusAutomations)
                {
                    var rockContext = new RockContext();
                    var connectionRequestService = new ConnectionRequestService(rockContext);
                    var connectionRequestQry     = connectionRequestService.Queryable().Include(a => a.AssignedGroup.Members).Where(a => a.ConnectionStatusId == connectionStatus.Id);
                    if (connectionStatusAutomation.DataViewId.HasValue)
                    {
                        // Get the dataview configured for the connection request
                        var dataViewService = new DataViewService(rockContext);
                        var dataview        = dataViewService.Get(connectionStatusAutomation.DataViewId.Value);

                        if (dataview == null)
                        {
                            errorMessages.Add($"The dataview {connectionStatusAutomation.DataViewId} for Connection Type {connectionTypeView.ConnectionTypeId} did not resolve");
                            continue;
                        }

                        // Now we'll filter our connection request query to only include the ones that are in the configured data view.
                        var dataViewGetQueryArgs = new DataViewGetQueryArgs
                        {
                            DbContext = rockContext
                        };

                        IQueryable <ConnectionRequest> dataviewQuery;
                        try
                        {
                            dataviewQuery = dataview.GetQuery(dataViewGetQueryArgs) as IQueryable <ConnectionRequest>;
                        }
                        catch (Exception ex)
                        {
                            errorMessages.Add(ex.Message);
                            ExceptionLogService.LogException(ex);
                            continue;
                        }

                        if (dataviewQuery == null)
                        {
                            errorMessages.Add($"Generating a query for dataview {connectionStatusAutomation.DataViewId} for Status {connectionStatus.Id} in Connection Type {connectionTypeView.ConnectionTypeId} was not successful");
                            continue;
                        }

                        connectionRequestQry = connectionRequestQry.Where(a => dataviewQuery.Any(b => b.Id == a.Id));
                    }

                    var eligibleConnectionRequests = new List <ConnectionRequest>();
                    if (connectionStatusAutomation.GroupRequirementsFilter != GroupRequirementsFilter.Ignore)
                    {
                        var connectionRequests = connectionRequestQry.ToList();
                        foreach (var connectionRequest in connectionRequests)
                        {
                            // Group Requirement can't be met when either placement group or placement group role id is missing
                            if (connectionRequest.AssignedGroupId.HasValue && connectionRequest.AssignedGroupMemberRoleId.HasValue)
                            {
                                var groupView = GetGroupView(connectionRequest, groupViews, rockContext);
                                if (groupView != null && groupView.HasGroupRequirement)
                                {
                                    var isRequirementMet = IsGroupRequirementMet(connectionRequest, groupView, rockContext);

                                    // connection request based on if group requirement is met or not is added to list for status update
                                    if ((connectionStatusAutomation.GroupRequirementsFilter == GroupRequirementsFilter.DoesNotMeet && !isRequirementMet) ||
                                        (connectionStatusAutomation.GroupRequirementsFilter == GroupRequirementsFilter.MustMeet && isRequirementMet))
                                    {
                                        eligibleConnectionRequests.Add(connectionRequest);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        eligibleConnectionRequests = connectionRequestQry.ToList();
                    }

                    var updatedCount = 0;
                    foreach (var connectionRequest in eligibleConnectionRequests)
                    {
                        connectionRequest.ConnectionStatusId = connectionStatusAutomation.DestinationStatusId;
                        updatedCount++;
                    }

                    rockContext.SaveChanges();
                    updatedResults.Add(updatedCount);
                }
            }
        }
Exemple #14
0
        /// <summary>
        /// Processes the connection type.
        /// </summary>
        /// <param name="connectionTypeView">The connection type view.</param>
        /// <param name="updatedResults">The updated results.</param>
        /// <param name="errorMessages">The error message.</param>
        private void ProcessConnectionType(
            ConnectionTypeView connectionTypeView,
            ConcurrentBag <int> updatedResults,
            out List <string> errorMessages)
        {
            errorMessages = new List <string>();
            var groupViews = new List <GroupView>();

            foreach (var connectionStatus in connectionTypeView.ConnectionStatuses)
            {
                foreach (var connectionStatusAutomation in connectionStatus.ConnectionStatusAutomations.OrderBy(a => a.AutomationName))
                {
                    var rockContext = new RockContext();
                    rockContext.Database.CommandTimeout = commandTimeout;

                    var connectionRequestService = new ConnectionRequestService(rockContext);
                    var destinationStatusId      = connectionStatusAutomation.DestinationStatusId;

                    // Limit to connection requests that don't already have the same connection status that this automation sets it to
                    var connectionRequestQry = connectionRequestService.Queryable()
                                               .Where(a => a.ConnectionStatusId == connectionStatus.Id && a.ConnectionStatusId != connectionStatusAutomation.DestinationStatusId)
                                               .Include(a => a.ConnectionOpportunity).Include(a => a.PersonAlias);

                    if (connectionStatusAutomation.GroupRequirementsFilter != GroupRequirementsFilter.Ignore)
                    {
                        // if we need to process GroupRequirements, include AssignedGroup.Members to avoid some lazy loading.
                        connectionRequestQry = connectionRequestQry.Include(a => a.AssignedGroup.Members);
                    }

                    if (connectionStatusAutomation.DataViewId.HasValue)
                    {
                        // Get the dataview configured for the connection request
                        var dataViewService = new DataViewService(rockContext);
                        var dataview        = dataViewService.Get(connectionStatusAutomation.DataViewId.Value);

                        if (dataview == null)
                        {
                            errorMessages.Add($"The dataview {connectionStatusAutomation.DataViewId} for Connection Type {connectionTypeView.ConnectionTypeId} did not resolve");
                            continue;
                        }

                        IQueryable <ConnectionRequest> dataviewQuery;
                        try
                        {
                            dataviewQuery = connectionRequestService.GetQueryUsingDataView(dataview);
                        }
                        catch (Exception ex)
                        {
                            errorMessages.Add(ex.Message);
                            ExceptionLogService.LogException(ex);
                            continue;
                        }

                        if (dataviewQuery == null)
                        {
                            errorMessages.Add($"Generating a query for dataview {connectionStatusAutomation.DataViewId} for Status {connectionStatus.Id} in Connection Type {connectionTypeView.ConnectionTypeId} was not successful");
                            continue;
                        }

                        connectionRequestQry = connectionRequestQry.Where(a => dataviewQuery.Any(b => b.Id == a.Id));
                    }

                    var eligibleConnectionRequests = new List <ConnectionRequest>();
                    if (connectionStatusAutomation.GroupRequirementsFilter != GroupRequirementsFilter.Ignore)
                    {
                        var connectionRequests = connectionRequestQry.ToList();
                        foreach (var connectionRequest in connectionRequests)
                        {
                            // Group Requirement can't be met when either placement group or placement group role id is missing
                            if (connectionRequest.AssignedGroupId.HasValue && connectionRequest.AssignedGroupMemberRoleId.HasValue)
                            {
                                var groupView = GetGroupView(connectionRequest, groupViews, rockContext);
                                if (groupView != null && groupView.HasGroupRequirement)
                                {
                                    var isRequirementMet = IsGroupRequirementMet(connectionRequest, groupView, rockContext);

                                    // connection request based on if group requirement is met or not is added to list for status update
                                    if ((connectionStatusAutomation.GroupRequirementsFilter == GroupRequirementsFilter.DoesNotMeet && !isRequirementMet) ||
                                        (connectionStatusAutomation.GroupRequirementsFilter == GroupRequirementsFilter.MustMeet && isRequirementMet))
                                    {
                                        eligibleConnectionRequests.Add(connectionRequest);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        eligibleConnectionRequests = connectionRequestQry.ToList();
                    }

                    var updatedCount = 0;
                    foreach (var connectionRequest in eligibleConnectionRequests)
                    {
                        if (connectionRequest.ConnectionStatusId == connectionStatusAutomation.DestinationStatusId)
                        {
                            continue;
                        }

                        connectionRequest.SetConnectionStatusFromAutomationLoop(connectionStatusAutomation);
                        updatedCount++;
                    }

                    if (updatedCount > 0)
                    {
                        rockContext.SaveChanges();
                        updatedResults.Add(updatedCount);
                    }
                }
            }
        }
        public void Execute(IJobExecutionContext context)
        {
            var rockContext     = new RockContext();
            var dataMap         = context.JobDetail.JobDataMap;
            var systemEmailGuid = dataMap.GetString("Email").AsGuidOrNull();

            string appRoot = Rock.Web.Cache.GlobalAttributesCache.Read().GetValue("PublicApplicationRoot");

            if (appRoot.IsNullOrWhiteSpace())
            {
                throw new Exception("Couldn't fetch application root!");
            }

            if (systemEmailGuid == null)
            {
                throw new Exception("A system email template needs to be set.");
            }
            var systemEmailTemplate = new SystemEmailService(rockContext).Get(systemEmailGuid.Value);

            if (systemEmailTemplate == null)
            {
                throw new Exception("The system email template setting is not a valid system email template.");
            }

            var cutOffHours = dataMap.GetString("ExcludeHours").AsIntegerOrNull();

            if (!cutOffHours.HasValue)
            {
                throw new Exception("A cutoff period needs to be set.");
            }



            var cutoff = RockDateTime.Now.AddHours(-1 * cutOffHours.Value);


            var connectionRequestService = new ConnectionRequestService(rockContext);
            var midnightToday            = new DateTime(RockDateTime.Now.Year, RockDateTime.Now.Month, RockDateTime.Now.Day);
            var currentDateTime          = RockDateTime.Now;
            var openConnectionRequests   =
                connectionRequestService.Queryable()
                .AsNoTracking()
                .Where(cr => cr.CreatedDateTime < cutoff && (cr.ConnectionState == ConnectionState.Active || (cr.ConnectionState == ConnectionState.FutureFollowUp && cr.FollowupDate.HasValue && cr.FollowupDate.Value < midnightToday)));

            if (!openConnectionRequests.Any())
            {
                context.Result = "There are no open and assigned connection requests to send reminders for";
                return;
            }

            int totalCriticalCount = openConnectionRequests.Count(cr => cr.ConnectionStatus.IsCritical);
            int totalIdleCount     = openConnectionRequests
                                     .Count(cr =>
                                            (cr.ConnectionRequestActivities.Any() && cr.ConnectionRequestActivities.Max(ra => ra.CreatedDateTime) < SqlFunctions.DateAdd("day", -cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle, currentDateTime)) ||
                                            (!cr.ConnectionRequestActivities.Any() && cr.CreatedDateTime < SqlFunctions.DateAdd("day", -cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle, currentDateTime))
                                            );

            var groupedRequests = openConnectionRequests
                                  .Where(cr => cr.ConnectorPersonAliasId != null)
                                  .GroupBy(cr => cr.ConnectorPersonAlias);

            int mailedCount = 0;

            foreach (var connectionRequestGrouping in groupedRequests)
            {
                var connectionRequests = connectionRequestGrouping.ToList();

                var mergeFields = new Dictionary <string, object>
                {
                    { "ConnectionRequests", connectionRequests },
                    { "Person", connectionRequestGrouping.Key.Person },
                    { "CriticalCount", connectionRequests.Count(cr => cr.ConnectionStatus.IsCritical) },
                    { "IdleCount", connectionRequests.Count(cr =>
                        {
                            var idleDate = currentDateTime.AddDays(-cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle);
                            return(cr.ConnectionRequestActivities.Any() &&
                                   cr.ConnectionRequestActivities.Max(ra => ra.CreatedDateTime) < idleDate ||
                                   (!cr.ConnectionRequestActivities.Any() && cr.CreatedDateTime < idleDate));
                        }) },
                    { "TotalIdleCount", totalIdleCount },
                    { "TotalCriticalCount", totalCriticalCount }
                };

                var recipients = new List <string> {
                    connectionRequestGrouping.Key.Person.Email
                };

                Email.Send(systemEmailTemplate.From.ResolveMergeFields(mergeFields), systemEmailTemplate.FromName.ResolveMergeFields(mergeFields), systemEmailTemplate.Subject.ResolveMergeFields(mergeFields), recipients, systemEmailTemplate.Body.ResolveMergeFields(mergeFields), appRoot, null, null);
                mailedCount++;
            }
            context.Result = string.Format("{0} reminders were sent ", mailedCount);
        }
Exemple #16
0
        /// <summary>
        /// Trigger Future Followup Workflow
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="futureFollowupDateWorkflows">The future follow-up date workflows.</param>
        /// <returns></returns>
        private string TriggerFutureFollowupWorkFlow(IJobExecutionContext context, List <ConnectionWorkflow> futureFollowupDateWorkflows)
        {
            try
            {
                JobDataMap dataMap = context.JobDetail.JobDataMap;

                context.UpdateLastStatusMessage($"Processing future follow-up workFlows.");

                int recordsUpdated   = 0;
                int triggerWorkflow  = 0;
                int recordsWithError = 0;

                var rockContext = new RockContext();

                DateTime midnightToday = RockDateTime.Today.AddDays(1);

                var connectionRequestService   = new ConnectionRequestService(rockContext);
                var eligibleConnectionRequests = connectionRequestService
                                                 .Queryable("ConnectionRequestWorkflows")
                                                 .AsNoTracking()
                                                 .Where(c => c.ConnectionState == ConnectionState.FutureFollowUp &&
                                                        c.FollowupDate.HasValue &&
                                                        c.FollowupDate < midnightToday)
                                                 .ToList();

                foreach (var connectionRequest in eligibleConnectionRequests)
                {
                    try
                    {
                        using (var updateRockContext = new RockContext())
                        {
                            // increase the timeout just in case.
                            updateRockContext.Database.CommandTimeout = 180;
                            updateRockContext.SourceOfChange          = SOURCE_OF_CHANGE;
                            var connectionOpportunity = connectionRequest.ConnectionOpportunity;
                            if (connectionOpportunity != null)
                            {
                                var opportunityWorkflows = futureFollowupDateWorkflows
                                                           .Where(w =>
                                                                  (w.ConnectionOpportunityId.HasValue && w.ConnectionOpportunityId.Value == connectionOpportunity.Id) ||
                                                                  (w.ConnectionTypeId.HasValue && w.ConnectionTypeId.Value == connectionOpportunity.ConnectionTypeId));

                                foreach (var connectionWorkflow in opportunityWorkflows)
                                {
                                    LaunchWorkflow(updateRockContext, connectionRequest, connectionWorkflow, ConnectionWorkflowTriggerType.FutureFollowupDateReached.ConvertToString());
                                    triggerWorkflow += 1;
                                }

                                updateRockContext.ConnectionRequests.Attach(connectionRequest);
                                connectionRequest.ConnectionState = ConnectionState.Active;

                                var guid = Rock.SystemGuid.ConnectionActivityType.FUTURE_FOLLOWUP_COMPLETE.AsGuid();
                                var futureFollowupCompleteActivityId = new ConnectionActivityTypeService(rockContext)
                                                                       .Queryable()
                                                                       .Where(t => t.Guid == guid)
                                                                       .Select(t => t.Id)
                                                                       .FirstOrDefault();

                                ConnectionRequestActivity connectionRequestActivity = new ConnectionRequestActivity();
                                connectionRequestActivity.ConnectionRequestId      = connectionRequest.Id;
                                connectionRequestActivity.ConnectionOpportunityId  = connectionRequest.ConnectionOpportunityId;
                                connectionRequestActivity.ConnectionActivityTypeId = futureFollowupCompleteActivityId;
                                new ConnectionRequestActivityService(updateRockContext).Add(connectionRequestActivity);
                                updateRockContext.SaveChanges();
                                recordsUpdated += 1;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // Log exception and keep on trucking.
                        ExceptionLogService.LogException(new Exception($"Exception occurred trying to trigger future followup workFlow:{connectionRequest.Id}.", ex), _httpContext);
                        recordsWithError += 1;
                    }
                }

                // Format the result message
                string result = $"{recordsUpdated:N0} connection request records triggered {triggerWorkflow} workflows.";
                if (recordsWithError > 0)
                {
                    result += $"{recordsWithError:N0} records logged an exception.";
                }

                return(result);
            }
            catch (Exception ex)
            {
                // Log exception and return the exception messages.
                ExceptionLogService.LogException(ex, _httpContext);

                return(ex.Messages().AsDelimited("; "));
            }
        }
        /// <summary>
        /// Handles the SelectPerson event of the ppRequestor control checking for possible duplicate records.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void ppRequestor_SelectPerson( object sender, EventArgs e )
        {
            if ( ppRequestor.PersonId.HasValue )
            {
                using ( var rockContext = new RockContext() )
                {
                    ConnectionRequestService connectionRequestService = new ConnectionRequestService( rockContext );

                    int connectionOpportunityId = hfConnectionOpportunityId.ValueAsInt();

                    // Check if this person already has a connection request for this opportunity.
                    var connectionRequest = connectionRequestService.Queryable()
                        .Where( r => r.PersonAliasId == ppRequestor.PersonAliasId.Value && r.ConnectionOpportunityId == connectionOpportunityId &&
                            ( r.ConnectionState == ConnectionState.Active || r.ConnectionState == ConnectionState.FutureFollowUp ) )
                        .FirstOrDefault();

                    if ( connectionRequest != null )
                    {
                        nbWarningMessage.Visible = true;
                        nbWarningMessage.Title = "Possible Duplicate: ";
                        nbWarningMessage.Text = string.Format( "There is already an active (or future follow up) request in the '{0}' opportunity for {1}. Are you sure you want to save this request?"
                            , connectionRequest.ConnectionOpportunity.PublicName, ppRequestor.PersonName.TrimEnd() );
                    }
                    else
                    {
                        nbWarningMessage.Visible = false;
                    }
                }
            }

            CheckGroupRequirement();
        }
        /// <summary>
        /// Updates the Connection Requests to us the new To person
        /// </summary>
        protected void UpdateConnectionRequests()
        {
            //Get the selected people
            FromPersonId = ppFrom.PersonId;
            ToPersonId = ppTo.PersonId;

            // Create Needed Services
            ConnectionRequestService connectionRequestService = new ConnectionRequestService(rockContext);

            //Get Connection Requests from From person
            var assigned = connectionRequestService.Queryable().Where(a => a.ConnectorPersonAliasId == FromPersonId);

            //Set each Connection Request in From person to To person
            foreach (var x in assigned)
            {
                x.ConnectorPersonAliasId = ToPersonId;
                x.ModifiedDateTime = DateTime.Now;
                x.ModifiedByPersonAliasId = CurrentPersonAliasId;
            }

            //Save changes
            rockContext.SaveChanges();

            //Update UI
            nbSuccess.Visible = true;
        }
        /// <summary>
        /// Returns the number of Workflows and Connection Requests for the selected Fron person, then populates grids.
        /// </summary>
        protected void UpdateUi()
        {
            // Get the selected person
            FromPersonId = ppFrom.PersonId;

            // Construct List
            var workflowResultList = new List<WorkflowActivity>();
            var connectionRequestResultList = new List<ConnectionRequest>();

            // Create Needed Services
            WorkflowActivityService workflowActivityService = new WorkflowActivityService(rockContext);
            ConnectionRequestService connectionRequestService = new ConnectionRequestService(rockContext);

            // Get Workflows from From person
            var assignedWorkflows =
                workflowActivityService.Queryable()
                    .Where(
                        a =>
                            a.AssignedPersonAliasId == FromPersonId && a.CompletedDateTime == null &&
                            a.Workflow.CompletedDateTime == null);

            // Get Connection Requests from From person
            var assignedConnectionRequests =
                connectionRequestService.Queryable()
                    .Where(
                        b =>
                            b.ConnectorPersonAliasId == FromPersonId && b.ConnectionState != ConnectionState.Connected &&
                            b.ConnectionState != ConnectionState.Inactive);

            // UI Updates
            if (ppFrom.PersonId != null)
            {
                foreach (var workflow in assignedWorkflows)
                {
                    workflowResultList.Add(workflow);
                }

                foreach (var connectionRequest in assignedConnectionRequests)
                {
                    connectionRequestResultList.Add(connectionRequest);
                }

                lbCount.Text = assignedWorkflows.Count() + " open workflows assigned to this person.<br />" +
                               assignedConnectionRequests.Count() + " open Connection Requests assigned to this person.";

                gWorkflows.DataSource = workflowResultList;
                gWorkflows.DataBind();

                gConnections.DataSource = connectionRequestResultList;
                gConnections.DataBind();

                if (assignedWorkflows.Any())
                {
                    btnSaveWorkflows.Visible = true;
                    ppTo.Visible = true;
                }

                if (assignedConnectionRequests.Any())
                {
                    btnSaveConnections.Visible = true;
                    ppTo.Visible = true;
                }
            }

            else
            {
                nbSuccess.Visible = false;
                nbWarningMessage.Visible = false;
            }
        }
        /// <summary>
        /// Handles the ItemDataBound event of the rConnectionTypes control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RepeaterItemEventArgs"/> instance containing the event data.</param>
        protected void rConnectionTypes_ItemDataBound( object sender, RepeaterItemEventArgs e )
        {
            var lConnectionOpportunityList = e.Item.FindControl( "lConnectionOpportunityList" ) as Literal;
            if ( lConnectionOpportunityList != null )
            {
                var connectionType = e.Item.DataItem as ConnectionType;
                var pageGuid = this.GetAttributeValue( "ConnectionRequestDetail" ).AsGuidOrNull();
                PageReference connectionRequestDetailPage = null;
                if ( pageGuid.HasValue )
                {
                    connectionRequestDetailPage = new PageReference( pageGuid.Value.ToString() );
                }

                if ( connectionType != null && this.Person != null )
                {
                    using ( var rockContext = new RockContext() )
                    {
                        int personId = this.Person.Id;
                        var connectionRequestService = new ConnectionRequestService( rockContext );
                        var connectionRequestList = connectionRequestService.Queryable().Where( a => a.PersonAlias.PersonId == personId && a.ConnectionOpportunity.ConnectionTypeId == connectionType.Id ).OrderBy( a => a.ConnectionOpportunity.Name ).AsNoTracking().ToList();
                        string listHtml = string.Empty;
                        foreach ( var connectionRequest in connectionRequestList )
                        {
                            string connectionNameHtml;
                            string connectionName;
                            if ( connectionRequest.CampusId.HasValue )
                            {
                                connectionName = string.Format( "{0} ({1})", connectionRequest.ConnectionOpportunity, CampusCache.Read( connectionRequest.CampusId.Value ) );
                            }
                            else
                            {
                                connectionName = string.Format( "{0}", connectionRequest.ConnectionOpportunity );
                            }

                            if ( connectionRequestDetailPage != null && connectionRequestDetailPage.PageId > 0 )
                            {
                                connectionRequestDetailPage.Parameters = new System.Collections.Generic.Dictionary<string, string>();
                                connectionRequestDetailPage.Parameters.Add( "ConnectionRequestId", connectionRequest.Id.ToString() );
                                connectionRequestDetailPage.Parameters.Add( "ConnectionOpportunityId", connectionRequest.ConnectionOpportunityId.ToString() );

                                connectionNameHtml = string.Format( "<a href='{0}'>{1}</a>", connectionRequestDetailPage.BuildUrl(), connectionName );
                            }
                            else
                            {
                                connectionNameHtml = connectionName;
                            }

                            listHtml += string.Format(
                                "<li {0}>{1} - <small>{2}</small></li>",
                                connectionRequest.ConnectionState == ConnectionState.Connected ? "class='is-inactive'" : string.Empty,
                                connectionNameHtml,
                                connectionRequest.ConnectionState == ConnectionState.Connected ? "Connected" : connectionRequest.ConnectionStatus.ToString() );
                        }

                        lConnectionOpportunityList.Text = listHtml;
                    }
                }
            }
        }
Exemple #21
0
        public virtual void Execute(IJobExecutionContext context)
        {
            JobDataMap dataMap                  = context.JobDetail.JobDataMap;
            var        rockContext              = new RockContext();
            var        groupService             = new GroupService(rockContext);
            var        groupMemberService       = new GroupMemberService(rockContext);
            var        connectionRequestService = new ConnectionRequestService(rockContext);

            var group = groupService.GetByGuid(dataMap.GetString("ConnectionGroup").AsGuid());

            var systemEmail = dataMap.GetString("SystemEmail").AsGuidOrNull();

            if (!systemEmail.HasValue)
            {
                throw new Exception("System Email is required!");
            }

            List <int> connectorPersonAliasIds = new List <int>();

            var recipients = new List <RecipientData>();

            if (group != null)
            {
                var childrenGroups = groupService.GetAllDescendents(group.Id);

                var allGroups = childrenGroups.ToList();

                allGroups.Add(group);

                connectorPersonAliasIds = allGroups.SelectMany(p => p.Members.Select(m => m.Person).SelectMany(psn => psn.Aliases).Select(a => a.Id)).ToList();
            }


            var connectionOpportunities = dataMap.GetString("ConnectionOpportunities").SplitDelimitedValues();

            // get job type id
            int jobId      = Convert.ToInt16(context.JobDetail.Description);
            var jobService = new ServiceJobService(rockContext);
            var job        = jobService.Get(jobId);

            DateTime      _midnightToday        = RockDateTime.Today.AddDays(1);
            var           currentDateTime       = RockDateTime.Now;
            PersonService personService         = new PersonService(rockContext);
            var           connectionRequestsQry = connectionRequestService.Queryable().Where(cr =>
                                                                                             connectionOpportunities.Contains(cr.ConnectionOpportunity.Guid.ToString()) &&
                                                                                             cr.ConnectorPersonAliasId != null &&
                                                                                             (
                                                                                                 cr.ConnectionState == ConnectionState.Active ||
                                                                                                 (cr.ConnectionState == ConnectionState.FutureFollowUp && cr.FollowupDate.HasValue && cr.FollowupDate.Value < _midnightToday)
                                                                                             ));

            // If we have a group of connectors, limit it to them.
            if (group != null)
            {
                List <int> groupconnectorPersonIds = group.ActiveMembers().SelectMany(gm => gm.Person.Aliases).Select(a => a.Id).ToList();
                connectionRequestsQry = connectionRequestsQry.Where(cr => cr.ConnectorPersonAliasId.HasValue && groupconnectorPersonIds.Contains(cr.ConnectorPersonAliasId.Value));
            }

            // Now get all the connection data for everyone.
            var connectionRequestGroups = connectionRequestsQry.GroupBy(cr => cr.ConnectorPersonAlias.PersonId);

            foreach (var connectionRequestGroup in connectionRequestGroups)
            {
                Person person = personService.Get(connectionRequestGroup.Key);
                List <ConnectionOpportunity> opportunities = connectionRequestGroup.Select(a => a.ConnectionOpportunity).Distinct().ToList();
                var newConnectionRequests = connectionRequestGroup.Where(cr => cr.CreatedDateTime >= job.LastSuccessfulRunDateTime).GroupBy(cr => cr.ConnectionOpportunityId).ToList();
                // Get all the idle connections
                var idleConnectionRequests = connectionRequestGroup
                                             .Where(cr => (
                                                        (cr.ConnectionRequestActivities.Any() && cr.ConnectionRequestActivities.Max(ra => ra.CreatedDateTime) < currentDateTime.AddDays(-cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle))) ||
                                                    (!cr.ConnectionRequestActivities.Any() && cr.CreatedDateTime < currentDateTime.AddDays(-cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle))
                                                    )
                                             .Select(a => new { ConnectionOpportunityId = a.ConnectionOpportunityId, Id = a.Id })
                                             .GroupBy(cr => cr.ConnectionOpportunityId).ToList();

                // get list of requests that have a status that is considered critical.
                var criticalConnectionRequests = connectionRequestGroup
                                                 .Where(r =>
                                                        r.ConnectionStatus.IsCritical
                                                        )
                                                 .Select(a => new { ConnectionOpportunityId = a.ConnectionOpportunityId, Id = a.Id })
                                                 .GroupBy(cr => cr.ConnectionOpportunityId).ToList();

                var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null);
                mergeFields.Add("Requests", connectionRequestGroup.Select(c => c).ToList());
                mergeFields.Add("ConnectionOpportunities", opportunities);
                mergeFields.Add("ConnectionRequests", connectionRequestGroup.GroupBy(cr => cr.ConnectionOpportunity).ToList());
                mergeFields.Add("NewConnectionRequests", newConnectionRequests);
                mergeFields.Add("IdleConnectionRequestIds", idleConnectionRequests);
                mergeFields.Add("CriticalConnectionRequestIds", criticalConnectionRequests);
                mergeFields.Add("Person", person);
                mergeFields.Add("LastRunDate", job.LastSuccessfulRunDateTime);
                mergeFields.Add("IncludeOpportunityBreakdown", dataMap.GetString("IncludeOpportunityBreakdown").AsBoolean());
                mergeFields.Add("IncludeAllRequests", dataMap.GetString("IncludeAllRequests").AsBoolean());

                recipients.Add(new RecipientData(person.Email, mergeFields));
            }

            // If we have valid recipients, send the email
            if (recipients.Count > 0)
            {
                RockEmailMessage email = new RockEmailMessage(systemEmail.Value);
                email.SetRecipients(recipients);
                email.CreateCommunicationRecord = dataMap.GetString("SaveCommunicationHistory").AsBoolean();
                email.Send();
            }

            context.Result = string.Format("{0} Connection reminders sent", recipients.Count);
        }
Exemple #22
0
        /// <summary>
        /// Trigger Future Followup Workflow
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="futureFollowupDateWorkflows">The future follow-up date workflows.</param>
        /// <returns></returns>
        private string TriggerFutureFollowupWorkFlow(IJobExecutionContext context, List <ConnectionWorkflow> futureFollowupDateWorkflows)
        {
            try
            {
                JobDataMap dataMap = context.JobDetail.JobDataMap;

                context.UpdateLastStatusMessage($"Processing future follow-up workFlows.");

                int recordsUpdated   = 0;
                int triggerWorkflow  = 0;
                int recordsWithError = 0;

                if (futureFollowupDateWorkflows.Any())
                {
                    var rockContext = new RockContext();

                    var connectionOpportunityIds = futureFollowupDateWorkflows
                                                   .Where(a => a.ConnectionOpportunityId.HasValue)
                                                   .Select(a => a.ConnectionOpportunityId.Value)
                                                   .ToList();

                    var connectionTypeIds = futureFollowupDateWorkflows
                                            .Where(a => a.ConnectionTypeId.HasValue)
                                            .Select(a => a.ConnectionTypeId.Value)
                                            .ToList();

                    var allConnectionOpportunities = new List <ConnectionOpportunity>();
                    if (connectionOpportunityIds.Any() || connectionTypeIds.Any())
                    {
                        var relatedConnectionOpportunities = new ConnectionOpportunityService(rockContext)
                                                             .Queryable()
                                                             .AsNoTracking()
                                                             .Where(o => connectionOpportunityIds.Contains(o.Id) || connectionTypeIds.Contains(o.ConnectionTypeId))
                                                             .ToList();
                        allConnectionOpportunities.AddRange(relatedConnectionOpportunities);
                    }


                    if (allConnectionOpportunities.Any())
                    {
                        connectionOpportunityIds = allConnectionOpportunities.Select(a => a.Id).ToList();
                        var      numberOfDaysToLookBack = dataMap.GetString(AttributeKeys.NumberOfDaysToLookBack).AsInteger();
                        DateTime midnightToday          = RockDateTime.Today.AddDays(1);
                        DateTime startDate = RockDateTime.Today.AddDays(-numberOfDaysToLookBack);

                        var connectionRequestService   = new ConnectionRequestService(rockContext);
                        var eligibleConnectionRequests = connectionRequestService
                                                         .Queryable("ConnectionRequestWorkflows")
                                                         .AsNoTracking()
                                                         .Where(c => connectionOpportunityIds.Contains(c.ConnectionOpportunityId) &&
                                                                c.ConnectionState == ConnectionState.FutureFollowUp &&
                                                                c.FollowupDate.HasValue &&
                                                                c.FollowupDate >= startDate &&
                                                                c.FollowupDate < midnightToday
                                                                )
                                                         .ToList();

                        foreach (var connectionRequest in eligibleConnectionRequests)
                        {
                            try
                            {
                                using (var updateRockContext = new RockContext())
                                {
                                    // increase the timeout just in case.
                                    updateRockContext.Database.CommandTimeout = 180;
                                    updateRockContext.SourceOfChange          = SOURCE_OF_CHANGE;
                                    var connectionOpportunity = allConnectionOpportunities.SingleOrDefault(a => a.Id == connectionRequest.ConnectionOpportunityId);
                                    if (connectionOpportunity != null)
                                    {
                                        var opportunityWorkflows = futureFollowupDateWorkflows
                                                                   .Where(w =>
                                                                          (w.ConnectionOpportunityId.HasValue && w.ConnectionOpportunityId.Value == connectionOpportunity.Id) ||
                                                                          (w.ConnectionTypeId.HasValue && w.ConnectionTypeId.Value == connectionOpportunity.ConnectionTypeId));

                                        foreach (var connectionWorkflow in opportunityWorkflows
                                                 .Where(a => !connectionRequest.ConnectionRequestWorkflows.Any(b => b.ConnectionWorkflowId == a.Id)))
                                        {
                                            LaunchWorkflow(updateRockContext, connectionRequest, connectionWorkflow, ConnectionWorkflowTriggerType.FutureFollowupDateReached.ConvertToString());
                                            triggerWorkflow += 1;
                                        }

                                        updateRockContext.ConnectionRequests.Attach(connectionRequest);
                                        connectionRequest.ConnectionState = ConnectionState.Active;
                                        updateRockContext.SaveChanges();
                                        recordsUpdated += 1;
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                // Log exception and keep on trucking.
                                ExceptionLogService.LogException(new Exception($"Exception occurred trying to trigger future followup workFlow:{connectionRequest.Id}.", ex), _httpContext);
                                recordsWithError += 1;
                            }
                        }
                    }
                }

                // Format the result message
                string result = $"{recordsUpdated:N0} connection request records triggered {triggerWorkflow} workflows.";
                if (recordsWithError > 0)
                {
                    result += $"{recordsWithError:N0} records logged an exception.";
                }

                return(result);
            }
            catch (Exception ex)
            {
                // Log exception and return the exception messages.
                ExceptionLogService.LogException(ex, _httpContext);

                return(ex.Messages().AsDelimited("; "));
            }
        }
Exemple #23
0
        /// <summary>
        /// Binds the grid.
        /// </summary>
        private void BindGrid()
        {
            var rockContext = new RockContext();

            var campaignConnectionItems = Rock.Web.SystemSettings.GetValue(CampaignConnectionKey.CAMPAIGN_CONNECTION_CONFIGURATION).FromJsonOrNull <List <CampaignItem> >() ?? new List <CampaignItem>();

            var relatedOpportunityIds = campaignConnectionItems.Select(a => a.OpportunityGuid).ToList();
            List <ConnectionOpportunity> relatedOpportunities      = new List <ConnectionOpportunity>();
            Dictionary <Guid, int>       activeOpportunityRequests = new Dictionary <Guid, int>();

            if (relatedOpportunityIds.Any())
            {
                var connectionOpportunityService = new ConnectionOpportunityService(rockContext);
                var connectionRequestService     = new ConnectionRequestService(rockContext);
                var connectionRequestsQry        = connectionRequestService.Queryable();
                relatedOpportunities = connectionOpportunityService.GetListByGuids(relatedOpportunityIds);
                foreach (var connectionOpportunity in relatedOpportunities)
                {
                    var activeRequestCount = connectionRequestsQry
                                             .Where(a => a.ConnectionOpportunityId == connectionOpportunity.Id &&
                                                    (a.ConnectionState == ConnectionState.Active ||
                                                     (a.ConnectionState == ConnectionState.FutureFollowUp && a.FollowupDate.HasValue && a.FollowupDate.Value < _midnightToday)))
                                             .Count();

                    activeOpportunityRequests.AddOrReplace(connectionOpportunity.Guid, activeRequestCount);
                }
            }

            var             relatedDataViewIds = campaignConnectionItems.Select(a => a.DataViewGuid).ToList();
            List <DataView> relatedDataViews   = new List <DataView>();

            if (relatedDataViewIds.Any())
            {
                var dataViewService = new DataViewService(rockContext);
                relatedDataViews = dataViewService.GetListByGuids(relatedDataViewIds);
            }

            var campaignConnectionRows = new List <CampaignConnectionRow>();
            var entitySetItemQry       = new EntitySetItemService(rockContext).Queryable();

            foreach (var campaignConnectionItem in campaignConnectionItems)
            {
                var campaignConnectionRow = new CampaignConnectionRow();
                campaignConnectionRow.Guid = campaignConnectionItem.Guid;
                campaignConnectionRow.Name = campaignConnectionItem.Name;
                campaignConnectionRow.ConnectionOpportunity = relatedOpportunities.FirstOrDefault(a => a.Guid == campaignConnectionItem.OpportunityGuid);
                campaignConnectionRow.DataView           = relatedDataViews.FirstOrDefault(a => a.Guid == campaignConnectionItem.DataViewGuid);
                campaignConnectionRow.ActiveRequests     = activeOpportunityRequests.GetValueOrNull(campaignConnectionItem.OpportunityGuid) ?? 0;
                campaignConnectionRow.PendingConnections = entitySetItemQry.Where(a => a.EntitySetId == campaignConnectionItem.EntitySetId).Count();
                campaignConnectionRow.IsActive           = campaignConnectionItem.IsActive;
                campaignConnectionRows.Add(campaignConnectionRow);
            }

            var qry = campaignConnectionRows.AsQueryable();

            SortProperty sortProperty = gCampaigns.SortProperty;

            if (sortProperty != null)
            {
                qry = qry.Sort(sortProperty);
            }
            else
            {
                qry = qry.OrderBy(g => g.Name);
            }

            gCampaigns.DataSource = qry.ToList();
            gCampaigns.DataBind();
        }
Exemple #24
0
        /// <summary>
        /// creates or updates the entity set on the basis of campaign connection configuration, and returns the Id of the entitySetId
        /// </summary>
        /// <param name="campaignConfiguration">The campaign configuration.</param>
        /// <returns></returns>
        public static int GetEntitySet(CampaignItem campaignConfiguration)
        {
            var rockContext = new RockContext();

            var connectionOpportunityService = new ConnectionOpportunityService(rockContext);
            var connectionRequestService     = new ConnectionRequestService(rockContext);
            var entitySetService             = new Rock.Model.EntitySetService(rockContext);

            var connectionOpportunity = connectionOpportunityService.Get(campaignConfiguration.OpportunityGuid);

            // list of person on the basis of Dataview result and optout group.
            var filteredPersonIds = GetFilteredPersonIds(campaignConfiguration, rockContext);

            // get the last connection datetime.
            var lastConnectionDateTime = RockDateTime.Now.AddDays(-campaignConfiguration.DaysBetweenConnection);

            // if DaysBetweenConnection is 0 then check for connection request for any time period.
            if (campaignConfiguration.DaysBetweenConnection == default(int))
            {
                lastConnectionDateTime = DateTime.MinValue;
            }

            // list of person that has active connection request OR has connection closed in the past number of days between connection.
            var excludedPersonIds = connectionRequestService
                                    .Queryable()
                                    .Where(a =>
                                           a.ConnectionOpportunityId == connectionOpportunity.Id && (
                                               a.ConnectionState == ConnectionState.Active ||
                                               a.ConnectionState == ConnectionState.FutureFollowUp ||
                                               ((a.ConnectionState == ConnectionState.Connected || a.ConnectionState == ConnectionState.Inactive) && a.ModifiedDateTime > lastConnectionDateTime)))
                                    .Select(a => a.PersonAlias.PersonId)
                                    .ToList();

            // filtered list of person removing all the personIds found in excludedPersonIds List
            filteredPersonIds = filteredPersonIds.Where(a => !excludedPersonIds.Contains(a)).ToList();

            // get the ordered list of personIds based on the oldest previous connection request and connection opportunity

            /* 2020-05-06 MDP
             * If there are many filteredPersonIds, we'll get a SQL Exception, so let's get *all* the Connected connection Requests first,
             * and then use C# to filter.
             */

            var orderedLastCompletedRequestForPerson = connectionRequestService
                                                       .Queryable()
                                                       .Where(a => a.ConnectionOpportunityId == connectionOpportunity.Id &&
                                                              a.ConnectionState == ConnectionState.Connected)
                                                       .GroupBy(a => a.PersonAlias.PersonId)
                                                       .Select(a => new
            {
                PersonId = a.Key,
                LastConnectionDateTime = a.OrderByDescending(b => b.ModifiedDateTime).Select(b => b.ModifiedDateTime).FirstOrDefault()
            })
                                                       .OrderBy(a => a.LastConnectionDateTime)
                                                       .Select(a => a.PersonId).ToList();

            // Use C# to filter persons so we can avoid a SQL Exception
            orderedLastCompletedRequestForPerson = orderedLastCompletedRequestForPerson.Where(a => filteredPersonIds.Contains(a)).ToList();

            var random = new Random();

            //// get the final ordered list of personIds based on the oldest previous connection request and
            //// connection opportunity otherwise order randomly for the person who don't have any previous connection request.
            var orderedPersonIds = filteredPersonIds
                                   .OrderBy(a =>
            {
                var index = orderedLastCompletedRequestForPerson.IndexOf(a);
                if (index == -1)
                {
                    return(random.Next(orderedLastCompletedRequestForPerson.Count, int.MaxValue));
                }
                else
                {
                    return(index);
                }
            }).ToList();

            EntitySet entitySet = null;

            if (campaignConfiguration.EntitySetId != default(int))
            {
                entitySet = entitySetService.Get(campaignConfiguration.EntitySetId);
            }

            List <Rock.Model.EntitySetItem> entitySetItems = new List <Rock.Model.EntitySetItem>();
            var personEntityTypeId = EntityTypeCache.Get <Rock.Model.Person>().Id;

            if (entitySet == null || entitySet.EntityTypeId != personEntityTypeId)
            {
                entitySet = new Rock.Model.EntitySet();
                entitySet.EntityTypeId   = personEntityTypeId;
                entitySet.ExpireDateTime = null;
                entitySetService.Add(entitySet);
            }
            else
            {
                var entitySetItemQry = new EntitySetItemService(rockContext)
                                       .Queryable().AsNoTracking()
                                       .Where(i => i.EntitySetId == entitySet.Id);
                rockContext.BulkDelete(entitySetItemQry);
            }

            // Update the EntitySet name
            entitySet.Name = campaignConfiguration.Name;

            var orderIndex = 0;

            foreach (var personId in orderedPersonIds)
            {
                try
                {
                    var item = new Rock.Model.EntitySetItem();
                    item.Order    = orderIndex++;
                    item.EntityId = personId;
                    entitySetItems.Add(item);
                }
                catch
                {
                    // ignore
                }
            }

            rockContext.SaveChanges();
            entitySetItems.ForEach(a =>
            {
                a.EntitySetId = entitySet.Id;
            });

            rockContext.BulkInsert(entitySetItems);

            return(entitySet.Id);
        }
Exemple #25
0
        /// <summary>
        /// Creates the connection requests.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="campaignItem">The campaign item.</param>
        /// <returns></returns>
        private int CreateConnectionRequests(IJobExecutionContext context, CampaignItem campaignItem)
        {
            context.UpdateLastStatusMessage($"Processing create connection requests for {campaignItem.Name}");

            // Skip creating connection requests if set to "AsNeeded" and DailyLimitAssigned is 0 or null
            if (campaignItem.CreateConnectionRequestOption == CreateConnectionRequestOptions.AsNeeded &&
                (campaignItem.DailyLimitAssigned <= 0 || campaignItem.DailyLimitAssigned == null))
            {
                return(0);
            }

            int recordsProcessed = 0;

            var rockContext = new RockContext();
            var connectionOpportunityService = new ConnectionOpportunityService(rockContext);
            var personAliasService           = new PersonAliasService(rockContext);
            var connectionRequestService     = new ConnectionRequestService(rockContext);

            var connectionOpportunity = connectionOpportunityService.Get(campaignItem.OpportunityGuid);

            if (connectionOpportunity == null)
            {
                return(0);
            }

            // get cutoff for the last connection datetime.
            var lastConnectionDateTime = RockDateTime.Now.AddDays(-campaignItem.DaysBetweenConnection);

            // if DaysBetweenConnection is 0 then check for connection request for any time period.
            if (campaignItem.DaysBetweenConnection == default(int))
            {
                lastConnectionDateTime = DateTime.MinValue;
            }

            var entitySetItemService = new EntitySetItemService(rockContext);

            var entitySetItemsQry = entitySetItemService
                                    .Queryable()
                                    .Where(a => a.EntitySetId == campaignItem.EntitySetId)
                                    .OrderBy(a => a.Order);

            bool autoAssignment     = false;
            var  eligibleConnectors = new List <ConnectionConnector>();

            if (campaignItem.CreateConnectionRequestOption == CreateConnectionRequestOptions.AsNeeded &&
                campaignItem.DailyLimitAssigned.HasValue &&
                campaignItem.DailyLimitAssigned != default(int))
            {
                autoAssignment     = true;
                eligibleConnectors = GetEligibleConnectorWithLimit(connectionOpportunity.Id, rockContext, campaignItem.DailyLimitAssigned.Value);
            }

            int?connectionStatusId = connectionOpportunity.ConnectionType.ConnectionStatuses
                                     .Where(s => s.IsDefault)
                                     .Select(s => ( int? )s.Id)
                                     .FirstOrDefault();

            // If opportunity doesn't have a default status, something is wrong
            if (connectionStatusId == null)
            {
                ExceptionLogService.LogException(new Exception($"Unable to determine default connection status for {connectionOpportunity.Name} while processing campaigns", null));
                return(0);
            }

            var dayofWeek         = RockDateTime.Now.DayOfWeek;
            var entitySetItemList = entitySetItemsQry.ToList();

            foreach (var entitySetItem in entitySetItemList)
            {
                var personAlias            = personAliasService.GetPrimaryAlias(entitySetItem.EntityId);
                var defaultCampus          = personAlias.Person.GetCampus();
                int?connectorPersonAliasId = null;
                if (autoAssignment)
                {
                    int?connectorPersonId = null;
                    if (campaignItem.PreferPreviousConnector)
                    {
                        var personIds = eligibleConnectors
                                        .Where(a => a.Limit - a.Current > 0 &&
                                               (!a.DaysOfWeek.Any() || a.DaysOfWeek.Contains(dayofWeek)) &&
                                               (!a.CampusId.HasValue || (a.CampusId.HasValue && defaultCampus != null && defaultCampus.Id == a.CampusId.Value)))
                                        .Select(a => a.PersonId)
                                        .ToList();

                        if (personIds.Any())
                        {
                            var person = connectionRequestService
                                         .Queryable()
                                         .Where(a => a.ConnectionOpportunityId == connectionOpportunity.Id &&
                                                a.PersonAlias.PersonId == personAlias.PersonId &&
                                                a.ConnectionState == ConnectionState.Connected &&
                                                a.ConnectorPersonAliasId.HasValue &&
                                                personIds.Contains(a.ConnectorPersonAlias.PersonId))
                                         .Select(a => a.ConnectorPersonAlias.Person)
                                         .FirstOrDefault();

                            if (person != null)
                            {
                                connectorPersonId = person.Id;
                            }
                        }
                    }

                    if (!connectorPersonId.HasValue)
                    {
                        var eligibleConnector = eligibleConnectors
                                                .Where(a => a.Limit - a.Current > 0 &&
                                                       (!a.DaysOfWeek.Any() || a.DaysOfWeek.Contains(dayofWeek)) &&
                                                       (!a.CampusId.HasValue || (a.CampusId.HasValue && defaultCampus != null && defaultCampus.Id == a.CampusId.Value)))
                                                .OrderBy(a => a.Current)     // order from least assigned to most assigned
                                                .ThenBy(x => Guid.NewGuid()) // and then randomize
                                                .FirstOrDefault();

                        if (eligibleConnector != null)
                        {
                            connectorPersonId = eligibleConnector.PersonId;
                        }
                    }

                    if (!connectorPersonId.HasValue)
                    {
                        continue;
                    }

                    foreach (var connectionConnector in eligibleConnectors.Where(a => a.PersonId == connectorPersonId.Value))
                    {
                        connectorPersonAliasId       = connectionConnector.PersonAliasId;
                        connectionConnector.Current += 1;
                    }
                }

                using (var insertRockContext = new RockContext())
                {
                    try
                    {
                        /*
                         *  3/30/2020 - NA
                         *
                         *  When setting the connection request's Requester, we have to use the PrimaryAlias
                         *  to set the connectionRequest.PersonAlias property because the ConnectionRequestChangeTransaction
                         *  https://github.com/SparkabilityGroup/Rock/blob/a556a9285b7fdfe5594441286242f4feaa5847f2/Rock/Transactions/ConnectionRequestChangeTransaction.cs#L123
                         *  (which handles triggered workflows) expects it.  Also, it needs to be tracked by
                         *  the current rockContext...
                         *
                         *  In other words, this will not work correctly:
                         *  PersonAliasId = personAlias.Id,
                         *
                         *  Reason: This plug-in cannot change Rock core assembly code.
                         */

                        var personPrimaryAlias = new PersonAliasService(insertRockContext).GetPrimaryAlias(entitySetItem.EntityId);
                        var connectionRequestActivityService = new ConnectionRequestActivityService(insertRockContext);
                        var insertConnectionRequestService   = new ConnectionRequestService(insertRockContext);

                        // double check that they haven't already been added
                        var personAlreadyHasConnectionRequest = CampaignConnectionHelper.PersonAlreadyHasConnectionRequest(connectionOpportunity.Id, rockContext, lastConnectionDateTime, entitySetItem.EntityId);

                        if (personAlreadyHasConnectionRequest)
                        {
                            continue;
                        }

                        var connectionRequest = new ConnectionRequest()
                        {
                            ConnectionOpportunityId = connectionOpportunity.Id,
                            PersonAlias             = personPrimaryAlias,
                            ConnectionState         = ConnectionState.Active,
                            ConnectorPersonAliasId  = connectorPersonAliasId,
                            CampusId           = defaultCampus?.Id,
                            ConnectionStatusId = connectionStatusId.Value,
                        };

                        if (campaignItem.RequestCommentsLavaTemplate.IsNotNullOrWhiteSpace())
                        {
                            var mergeFields = new Dictionary <string, object>();
                            mergeFields.Add("Person", personAlias.Person);
                            mergeFields.Add("Family", personAlias.Person.GetFamily());
                            connectionRequest.Comments = campaignItem.RequestCommentsLavaTemplate.ResolveMergeFields(mergeFields);
                        }

                        insertConnectionRequestService.Add(connectionRequest);

                        if (connectorPersonAliasId.HasValue)
                        {
                            var connectionActivityTypeAssignedGuid = Rock.SystemGuid.ConnectionActivityType.ASSIGNED.AsGuid();
                            int?assignedActivityId = new ConnectionActivityTypeService(rockContext).GetId(connectionActivityTypeAssignedGuid);
                            if (assignedActivityId.HasValue)
                            {
                                var connectionRequestActivity = new ConnectionRequestActivity();
                                connectionRequestActivity.ConnectionRequest        = connectionRequest;
                                connectionRequestActivity.ConnectionOpportunityId  = connectionRequest.ConnectionOpportunityId;
                                connectionRequestActivity.ConnectionActivityTypeId = assignedActivityId.Value;
                                connectionRequestActivity.ConnectorPersonAliasId   = connectorPersonAliasId;
                                connectionRequestActivityService.Add(connectionRequestActivity);
                            }
                        }

                        insertRockContext.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        // Log exception and keep on trucking.
                        var exception = new Exception($"Exception occurred trying to create connection request:{personAlias.Id}.", ex);
                        createConnectionRequestExceptions.Add(exception);
                        ExceptionLogService.LogException(exception, null);
                    }
                }

                recordsProcessed += 1;
            }

            return(recordsProcessed);
        }
Exemple #26
0
        /// <summary>
        /// Assigns the connection requests from the SelectedCampaign's entity set.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="selectedCampaignItem">The selected campaign item.</param>
        /// <param name="numberOfRequestsRemaining">The number of requests remaining.</param>
        /// <param name="connectorPerson">The connector person.</param>
        private static void AssignConnectionRequestsFromEntitySet(RockContext rockContext, CampaignItem selectedCampaignItem, ref int numberOfRequestsRemaining, Person connectorPerson)
        {
            var opportunityService            = new ConnectionOpportunityService(rockContext);
            ConnectionOpportunity opportunity = opportunityService.Get(selectedCampaignItem.OpportunityGuid);

            if (opportunity == null || !opportunity.IsActive)
            {
                return;
            }

            int?defaultStatusId = opportunity.ConnectionType.ConnectionStatuses
                                  .Where(s => s.IsDefault)
                                  .Select(s => ( int? )s.Id)
                                  .FirstOrDefault();

            // If opportunity doesn't have a default status, something is wrong
            if (defaultStatusId == null)
            {
                return;
            }

            var connectorCampusIds = GetConnectorCampusIds(selectedCampaignItem, connectorPerson);

            var connectionRequestService         = new ConnectionRequestService(rockContext);
            var connectionRequestActivityService = new ConnectionRequestActivityService(rockContext);

            // get previous connections for the connector that have the same campus of the connector, or if the person's campus or connector person's campus is null
            var previousConnectedPersonIdsForCurrentPerson = connectionRequestService.Queryable()
                                                             .Where(a => a.ConnectionOpportunityId == opportunity.Id)
                                                             .Where(a => a.ConnectorPersonAlias.PersonId == connectorPerson.Id)
                                                             .Where(a => (a.CampusId == null) || connectorCampusIds.Any(connectorCampusId => connectorCampusId == null || a.CampusId.Value == connectorCampusId))
                                                             .Select(a => a.PersonAlias.PersonId).Distinct().ToList();

            var entitySetId          = CampaignConnectionHelper.GetEntitySet(selectedCampaignItem);
            var entitySetItemService = new EntitySetItemService(rockContext);
            var entitySetItemList    = entitySetItemService.Queryable().Where(a => a.EntitySetId == entitySetId).OrderBy(a => a.Order).Select(a => new
            {
                PersonId        = a.EntityId,
                EntityItemOrder = a.Order
            }).ToList();

            if (selectedCampaignItem.PreferPreviousConnector)
            {
                // sort them by any where the current person was assigned to this person before
                entitySetItemList = entitySetItemList
                                    .OrderBy(a => previousConnectedPersonIdsForCurrentPerson.Any(x => x == a.PersonId))
                                    .ThenBy(a => a.EntityItemOrder).ToList();
            }
            else
            {
                entitySetItemList = entitySetItemList.OrderBy(a => a.EntityItemOrder).ToList();
            }

            var personService = new PersonService(rockContext);

            // get the last connection datetime.
            var lastConnectionDateTime = RockDateTime.Now.AddDays(-selectedCampaignItem.DaysBetweenConnection);

            // if DaysBetweenConnection is 0 then check for connection request for any time period.
            if (selectedCampaignItem.DaysBetweenConnection == default(int))
            {
                lastConnectionDateTime = DateTime.MinValue;
            }

            foreach (var entitySetItem in entitySetItemList)
            {
                var entitySetPerson = personService.Get(entitySetItem.PersonId);
                if (entitySetPerson == null)
                {
                    continue;
                }

                var entitySetPersonPrimaryCampusId = entitySetPerson.PrimaryCampusId;

                bool validCampus = IsValidCampus(connectorCampusIds, entitySetPersonPrimaryCampusId);
                if (!validCampus)
                {
                    continue;
                }

                // double check that they haven't already been added
                bool personAlreadyHasConnectionRequest = PersonAlreadyHasConnectionRequest(opportunity.Id, rockContext, lastConnectionDateTime, entitySetPerson.Id);

                if (personAlreadyHasConnectionRequest)
                {
                    continue;
                }

                var connectionRequest = new ConnectionRequest();
                connectionRequest.ConnectionOpportunityId = opportunity.Id;

                /*
                 *  3/30/2020 - NA
                 *
                 *  When setting the connection request's Requester, we have to use the PrimaryAlias
                 *  to set the connectionRequest.PersonAlias property because the ConnectionRequestChangeTransaction
                 *  https://github.com/SparkabilityGroup/Rock/blob/a556a9285b7fdfe5594441286242f4feaa5847f2/Rock/Transactions/ConnectionRequestChangeTransaction.cs#L123
                 *  (which handles triggered workflows) expects it.  Also, it needs to be tracked by
                 *  the current rockContext... hence the change from GetAsNoTracking() to just Get() above:
                 *  var entitySetPerson = personService.Get( entitySetItem.PersonId );
                 *
                 *  In other words, this will not work correctly:
                 *  connectionRequest.PersonAliasId = entitySetPerson.PrimaryAliasId.Value;
                 *
                 *  Reason: This plug-in cannot change Rock core assembly code.
                 */

                connectionRequest.PersonAlias            = entitySetPerson.PrimaryAlias;
                connectionRequest.ConnectionState        = ConnectionState.Active;
                connectionRequest.ConnectorPersonAliasId = connectorPerson.PrimaryAliasId;
                connectionRequest.CampusId           = entitySetPersonPrimaryCampusId;
                connectionRequest.ConnectionStatusId = defaultStatusId.Value;

                if (selectedCampaignItem.RequestCommentsLavaTemplate.IsNotNullOrWhiteSpace())
                {
                    var mergeFields = new Dictionary <string, object>();
                    mergeFields.Add("Person", entitySetPerson);
                    mergeFields.Add("Family", entitySetPerson.GetFamily());
                    connectionRequest.Comments = selectedCampaignItem.RequestCommentsLavaTemplate.ResolveMergeFields(mergeFields);
                }

                connectionRequestService.Add(connectionRequest);

                var connectionActivityTypeAssignedGuid = Rock.SystemGuid.ConnectionActivityType.ASSIGNED.AsGuid();
                int?assignedActivityId = new ConnectionActivityTypeService(rockContext).GetId(connectionActivityTypeAssignedGuid);
                if (assignedActivityId.HasValue)
                {
                    var connectionRequestActivity = new ConnectionRequestActivity();
                    connectionRequestActivity.ConnectionRequest        = connectionRequest;
                    connectionRequestActivity.ConnectionOpportunityId  = connectionRequest.ConnectionOpportunityId;
                    connectionRequestActivity.ConnectionActivityTypeId = assignedActivityId.Value;
                    connectionRequestActivity.ConnectorPersonAliasId   = connectorPerson.PrimaryAliasId;
                    connectionRequestActivityService.Add(connectionRequestActivity);
                }

                numberOfRequestsRemaining--;
                if (numberOfRequestsRemaining <= 0)
                {
                    break;
                }
            }
        }
        public void Execute(IJobExecutionContext context)
        {
            var      rockContext = new RockContext();
            var      dataMap     = context.JobDetail.JobDataMap;
            DateTime?lastRun     = null;

            if (context.PreviousFireTimeUtc.HasValue)
            {
                lastRun = RockDateTime.ConvertLocalDateTimeToRockDateTime(context.PreviousFireTimeUtc.Value.LocalDateTime);
            }

            var systemEmailGuid = dataMap.GetString("Email").AsGuidOrNull();

            string appRoot = Rock.Web.Cache.GlobalAttributesCache.Read().GetValue("PublicApplicationRoot");

            if (appRoot.IsNullOrWhiteSpace())
            {
                throw new Exception("Couldn't fetch application root!");
            }

            if (systemEmailGuid == null)
            {
                throw new Exception("A system email template needs to be set.");
            }

            var systemEmailTemplate = new SystemEmailService(rockContext).Get(systemEmailGuid.Value);

            if (systemEmailTemplate == null)
            {
                throw new Exception("The system email template setting is not a valid system email template.");
            }

            var cutOffHours = dataMap.GetString("IncludeHours").AsIntegerOrNull();

            if (!cutOffHours.HasValue)
            {
                throw new Exception("A cutoff period needs to be set.");
            }

            if (lastRun == null)
            {
                lastRun = RockDateTime.Now.AddHours(-1 * cutOffHours.Value);
            }

            var connectionRequestService = new ConnectionRequestService(rockContext);
            var openConnectionRequests   =
                connectionRequestService.Queryable()
                .AsNoTracking()
                .Where(cr => cr.CreatedDateTime >= lastRun && cr.ConnectionState != ConnectionState.Connected && cr.ConnectorPersonAliasId != null);

            if (!openConnectionRequests.Any())
            {
                context.Result = "There are no open and assigned connection requests to send alerts for";
                return;
            }

            var groupedRequests = openConnectionRequests
                                  .ToList()
                                  .GroupBy(cr => cr.ConnectorPersonAlias);

            int mailedCount = 0;

            foreach (var connectionRequestGrouping in groupedRequests)
            {
                if (connectionRequestGrouping.Key == null)
                {
                    continue;
                }
                var connectionRequests = connectionRequestGrouping.ToList();

                var mergeFields = new Dictionary <string, object>
                {
                    { "ConnectionRequests", connectionRequests },
                    { "Person", connectionRequestGrouping.Key.Person }
                };

                var recipients = new List <string> {
                    connectionRequestGrouping.Key.Person.Email
                };

                Email.Send(systemEmailTemplate.From.ResolveMergeFields(mergeFields), systemEmailTemplate.FromName.ResolveMergeFields(mergeFields), systemEmailTemplate.Subject.ResolveMergeFields(mergeFields), recipients, systemEmailTemplate.Body.ResolveMergeFields(mergeFields), appRoot, null);
                mailedCount++;
            }
            context.Result = string.Format("{0} reminders were sent ", mailedCount);
        }