/// <summary> /// Adds connection request(s) for the specified connectorPerson /// </summary> /// <param name="selectedCampaignItem">The selected campaign item.</param> /// <param name="connectorPerson">The connector person.</param> /// <param name="numberOfRequests">The number of requests.</param> /// <param name="numberOfRequestsRemaining">The number of requests remaining.</param> public static void AddConnectionRequestsForPerson(CampaignItem selectedCampaignItem, Person connectorPerson, int numberOfRequests, out int numberOfRequestsRemaining) { var rockContext = new RockContext(); numberOfRequestsRemaining = numberOfRequests; /* To assign requests, do the following in this order * - a) Get current connectionRequest records that don't have a connector and have a connection state of Active or a pastdue FutureFollowUp. * - b) If that runs out, get persons from the EntitySet of the selectedCampaignConnectionItem * - If there aren't enough from 'a' or 'b' */ IQueryable <ConnectionRequest> connectionRequestsWithoutConnectorQuery = GetConnectionRequestsWithoutConnectorQuery(rockContext, selectedCampaignItem, connectorPerson); numberOfRequestsRemaining = numberOfRequests; var connectionRequestsWithoutConnectorList = connectionRequestsWithoutConnectorQuery .OrderBy(a => a.CreatedDateTime) .ToList(); int connectorPersonAliasId = connectorPerson.PrimaryAliasId.Value; var connectionActivityTypeAssignedGuid = Rock.SystemGuid.ConnectionActivityType.ASSIGNED.AsGuid(); int?assignedActivityId = new ConnectionActivityTypeService(rockContext).GetId(connectionActivityTypeAssignedGuid); var connectionRequestActivityService = new ConnectionRequestActivityService(rockContext); foreach (var connectionRequest in connectionRequestsWithoutConnectorList) { connectionRequest.ConnectorPersonAliasId = connectorPersonAliasId; if (selectedCampaignItem.RequestCommentsLavaTemplate.IsNotNullOrWhiteSpace() && connectionRequest.Comments.IsNullOrWhiteSpace()) { var mergeFields = new Dictionary <string, object>(); mergeFields.Add("Person", connectionRequest.PersonAlias.Person); mergeFields.Add("Family", connectionRequest.PersonAlias.Person.GetFamily()); connectionRequest.Comments = selectedCampaignItem.RequestCommentsLavaTemplate.ResolveMergeFields(mergeFields); } /* * 4/1/2020 - NA * * You cannot attached the connectorPerson.PrimaryAlias to the connectionRequest.ConnectorPersonAlias * because they are tracked by two different contexts. Therefore this will not work: * connectionRequest.ConnectorPersonAlias = connectorPerson.PrimaryAlias; */ if (assignedActivityId.HasValue) { var connectionRequestActivity = new ConnectionRequestActivity(); connectionRequestActivity.ConnectionRequestId = connectionRequest.Id; connectionRequestActivity.ConnectionOpportunityId = connectionRequest.ConnectionOpportunityId; connectionRequestActivity.ConnectionActivityTypeId = assignedActivityId.Value; connectionRequestActivity.ConnectorPersonAliasId = connectorPersonAliasId; connectionRequestActivityService.Add(connectionRequestActivity); } numberOfRequestsRemaining--; if (numberOfRequestsRemaining <= 0) { break; } } rockContext.SaveChanges(); if (numberOfRequestsRemaining == 0) { // we were able to assign enough from connectionRequestsWithoutConnectorList, so save those changes and return return; } lock ( addConnectionRequestsLockObject ) { AssignConnectionRequestsFromEntitySet(rockContext, selectedCampaignItem, ref numberOfRequestsRemaining, connectorPerson); rockContext.SaveChanges(); } }
/// <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; } } }
/// <summary> /// Handles the Click event of the btnTransferSave control. /// </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 btnTransferSave_Click( object sender, EventArgs e ) { using ( var rockContext = new RockContext() ) { var connectionRequestService = new ConnectionRequestService( rockContext ); var connectionActivityTypeService = new ConnectionActivityTypeService( rockContext ); var connectionRequestActivityService = new ConnectionRequestActivityService( rockContext ); var connectionRequest = connectionRequestService.Get( hfConnectionRequestId.ValueAsInt() ); if ( connectionRequest != null ) { int? newOpportunityId = ddlTransferOpportunity.SelectedValueAsId(); int? newStatusId = ddlTransferStatus.SelectedValueAsId(); var guid = Rock.SystemGuid.ConnectionActivityType.TRANSFERRED.AsGuid(); var transferredActivityId = connectionActivityTypeService.Queryable() .Where( t => t.Guid == guid ) .Select( t => t.Id ) .FirstOrDefault(); if ( newOpportunityId.HasValue && newStatusId.HasValue && transferredActivityId > 0 ) { ConnectionRequestActivity connectionRequestActivity = new ConnectionRequestActivity(); connectionRequestActivity.ConnectionRequestId = connectionRequest.Id; connectionRequestActivity.ConnectionOpportunityId = newOpportunityId.Value; connectionRequestActivity.ConnectionActivityTypeId = transferredActivityId; connectionRequestActivity.Note = tbTransferNote.Text; connectionRequestActivityService.Add( connectionRequestActivity ); connectionRequest.ConnectionOpportunityId = newOpportunityId.Value; connectionRequest.ConnectionStatusId = newStatusId.Value; connectionRequest.AssignedGroupId = null; connectionRequest.AssignedGroupMemberRoleId = null; connectionRequest.AssignedGroupMemberStatus = null; if ( cbClearConnector.Checked ) { connectionRequest.ConnectorPersonAliasId = null; } rockContext.SaveChanges(); pnlReadDetails.Visible = true; wpConnectionRequestActivities.Visible = true; wpConnectionRequestWorkflow.Visible = true; pnlTransferDetails.Visible = false; ShowDetail( connectionRequest.Id, connectionRequest.ConnectionOpportunityId ); } } } }
/// <summary> /// Handles the Click event of the lbConnect control. /// </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 lbConnect_Click( object sender, EventArgs e ) { using ( var rockContext = new RockContext() ) { var connectionRequestService = new ConnectionRequestService( rockContext ); var groupMemberService = new GroupMemberService( rockContext ); var connectionActivityTypeService = new ConnectionActivityTypeService( rockContext ); var connectionRequestActivityService = new ConnectionRequestActivityService( rockContext ); var connectionRequest = connectionRequestService.Get( hfConnectionRequestId.ValueAsInt() ); if ( connectionRequest != null && connectionRequest.PersonAlias != null && connectionRequest.ConnectionOpportunity != null ) { bool okToConnect = true; GroupMember groupMember = null; // Only do group member placement if the request has an assigned placement group, role, and status if ( connectionRequest.AssignedGroupId.HasValue && connectionRequest.AssignedGroupMemberRoleId.HasValue && connectionRequest.AssignedGroupMemberStatus.HasValue ) { var group = new GroupService( rockContext ).Get( connectionRequest.AssignedGroupId.Value ); if ( group != null ) { // Only attempt the add if person does not already exist in group with same role groupMember = groupMemberService.GetByGroupIdAndPersonIdAndGroupRoleId( connectionRequest.AssignedGroupId.Value, connectionRequest.PersonAlias.PersonId, connectionRequest.AssignedGroupMemberRoleId.Value ); if ( groupMember == null ) { groupMember = new GroupMember(); groupMember.PersonId = connectionRequest.PersonAlias.PersonId; groupMember.GroupId = connectionRequest.AssignedGroupId.Value; groupMember.GroupRoleId = connectionRequest.AssignedGroupMemberRoleId.Value; groupMember.GroupMemberStatus = connectionRequest.AssignedGroupMemberStatus.Value; foreach ( ListItem item in cblManualRequirements.Items ) { if ( !item.Selected && group.MustMeetRequirementsToAddMember.HasValue && group.MustMeetRequirementsToAddMember.Value ) { okToConnect = false; nbRequirementsErrors.Text = "Group Requirements have not been met. Please verify all of the requirements."; nbRequirementsErrors.Visible = true; break; } else { groupMember.GroupMemberRequirements.Add( new GroupMemberRequirement { GroupRequirementId = item.Value.AsInteger(), RequirementMetDateTime = RockDateTime.Now, LastRequirementCheckDateTime = RockDateTime.Now } ); } } if ( okToConnect ) { groupMemberService.Add( groupMember ); if ( !string.IsNullOrWhiteSpace( connectionRequest.AssignedGroupMemberAttributeValues ) ) { var savedValues = JsonConvert.DeserializeObject<Dictionary<string, string>>( connectionRequest.AssignedGroupMemberAttributeValues ); if ( savedValues != null ) { groupMember.LoadAttributes(); foreach ( var item in savedValues ) { groupMember.SetAttributeValue( item.Key, item.Value ); } } } } } } } if ( okToConnect ) { // ... but always record the connection activity and change the state to connected. var guid = Rock.SystemGuid.ConnectionActivityType.CONNECTED.AsGuid(); var connectedActivityId = connectionActivityTypeService.Queryable() .Where( t => t.Guid == guid ) .Select( t => t.Id ) .FirstOrDefault(); if ( connectedActivityId > 0 ) { var connectionRequestActivity = new ConnectionRequestActivity(); connectionRequestActivity.ConnectionRequestId = connectionRequest.Id; connectionRequestActivity.ConnectionOpportunityId = connectionRequest.ConnectionOpportunityId; connectionRequestActivity.ConnectionActivityTypeId = connectedActivityId; connectionRequestActivity.ConnectorPersonAliasId = CurrentPersonAliasId; connectionRequestActivityService.Add( connectionRequestActivity ); } connectionRequest.ConnectionState = ConnectionState.Connected; rockContext.SaveChanges(); if ( groupMember != null && !string.IsNullOrWhiteSpace( connectionRequest.AssignedGroupMemberAttributeValues ) ) { groupMember.SaveAttributeValues( rockContext ); } ShowDetail( connectionRequest.Id, connectionRequest.ConnectionOpportunityId ); } } } }
/// <summary> /// Handles the Click event of the btnAddConnectionRequestActivity control. /// </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 btnAddConnectionRequestActivity_Click( object sender, EventArgs e ) { using ( var rockContext = new RockContext() ) { var connectionRequestService = new ConnectionRequestService( rockContext ); var connectionRequestActivityService = new ConnectionRequestActivityService( rockContext ); var personAliasService = new PersonAliasService( rockContext ); var connectionRequest = connectionRequestService.Get( hfConnectionRequestId.ValueAsInt() ); if ( connectionRequest != null ) { int? activityTypeId = ddlActivity.SelectedValueAsId(); int? personAliasId = personAliasService.GetPrimaryAliasId( ddlActivityConnector.SelectedValueAsId() ?? 0 ); if ( activityTypeId.HasValue && personAliasId.HasValue ) { ConnectionRequestActivity connectionRequestActivity = null; Guid? guid = hfAddConnectionRequestActivityGuid.Value.AsGuidOrNull(); if ( guid.HasValue ) { connectionRequestActivity = connectionRequestActivityService.Get( guid.Value ); } if ( connectionRequestActivity == null ) { connectionRequestActivity = new ConnectionRequestActivity(); connectionRequestActivity.ConnectionRequestId = connectionRequest.Id; connectionRequestActivity.ConnectionOpportunityId = connectionRequest.ConnectionOpportunityId; connectionRequestActivityService.Add( connectionRequestActivity ); } connectionRequestActivity.ConnectionActivityTypeId = activityTypeId.Value; connectionRequestActivity.ConnectorPersonAliasId = personAliasId.Value; connectionRequestActivity.Note = tbNote.Text; rockContext.SaveChanges(); BindConnectionRequestActivitiesGrid( connectionRequest, rockContext ); HideDialog(); } } } }
/// <summary> /// Handles the Click event of the btnSave control. /// </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 btnSave_Click( object sender, EventArgs e ) { if ( ! ppRequestor.PersonAliasId.HasValue ) { ShowErrorMessage( "Incomplete", "You must select a person to save a request." ); return; } if ( Page.IsValid ) { using ( var rockContext = new RockContext() ) { ConnectionRequestService connectionRequestService = new ConnectionRequestService( rockContext ); ConnectionRequest connectionRequest = null; int connectionRequestId = hfConnectionRequestId.ValueAsInt(); // if adding a new connection request if ( connectionRequestId.Equals( 0 ) ) { connectionRequest = new ConnectionRequest(); connectionRequest.ConnectionOpportunityId = hfConnectionOpportunityId.ValueAsInt(); if ( ddlCampus.SelectedValueAsId().HasValue ) { SetUserPreference( CAMPUS_SETTING, ddlCampus.SelectedValueAsId().Value.ToString() ); } } else { // load existing connection request connectionRequest = connectionRequestService.Get( connectionRequestId ); } var personAliasService = new PersonAliasService( rockContext ); int? oldConnectorPersonAliasId = connectionRequest.ConnectorPersonAliasId; int? newConnectorPersonId = ddlConnectorEdit.SelectedValueAsId(); int? newConnectorPersonAliasId = newConnectorPersonId.HasValue ? personAliasService.GetPrimaryAliasId( newConnectorPersonId.Value ) : (int?)null; connectionRequest.ConnectorPersonAliasId = newConnectorPersonAliasId; connectionRequest.PersonAlias = personAliasService.Get( ppRequestor.PersonAliasId.Value ); connectionRequest.ConnectionState = rblState.SelectedValueAsEnum<ConnectionState>(); connectionRequest.ConnectionStatusId = rblStatus.SelectedValueAsId().Value; if ( ddlCampus.SelectedValueAsId().HasValue ) { connectionRequest.CampusId = ddlCampus.SelectedValueAsId().Value; } connectionRequest.AssignedGroupId = ddlPlacementGroup.SelectedValueAsId(); connectionRequest.AssignedGroupMemberRoleId = ddlPlacementGroupRole.SelectedValueAsInt(); connectionRequest.AssignedGroupMemberStatus = ddlPlacementGroupStatus.SelectedValueAsEnumOrNull<GroupMemberStatus>(); connectionRequest.AssignedGroupMemberAttributeValues = GetGroupMemberAttributeValues(); connectionRequest.Comments = tbComments.Text.ScrubHtmlAndConvertCrLfToBr(); connectionRequest.FollowupDate = dpFollowUp.SelectedDate; if ( !Page.IsValid ) { return; } // if the connectionRequest IsValue is false, and the UI controls didn't report any errors, it is probably // because the custom rules of ConnectionRequest didn't pass. // So, make sure a message is displayed in the validation summary. cvConnectionRequest.IsValid = connectionRequest.IsValid; if ( !cvConnectionRequest.IsValid ) { cvConnectionRequest.ErrorMessage = connectionRequest.ValidationResults.Select( a => a.ErrorMessage ).ToList().AsDelimited( "<br />" ); return; } if ( connectionRequest.Id.Equals( 0 ) ) { connectionRequestService.Add( connectionRequest ); } rockContext.SaveChanges(); if ( newConnectorPersonAliasId.HasValue && !newConnectorPersonAliasId.Equals( oldConnectorPersonAliasId ) ) { var guid = Rock.SystemGuid.ConnectionActivityType.ASSIGNED.AsGuid(); var assignedActivityId = new ConnectionActivityTypeService( rockContext ).Queryable() .Where( t => t.Guid == guid ) .Select( t => t.Id ) .FirstOrDefault(); if ( assignedActivityId > 0 ) { var connectionRequestActivityService = new ConnectionRequestActivityService( rockContext ); var connectionRequestActivity = new ConnectionRequestActivity(); connectionRequestActivity.ConnectionRequestId = connectionRequest.Id; connectionRequestActivity.ConnectionOpportunityId = connectionRequest.ConnectionOpportunityId; connectionRequestActivity.ConnectionActivityTypeId = assignedActivityId; connectionRequestActivity.ConnectorPersonAliasId = newConnectorPersonAliasId; connectionRequestActivityService.Add( connectionRequestActivity ); rockContext.SaveChanges(); } } var qryParams = new Dictionary<string, string>(); qryParams["ConnectionRequestId"] = connectionRequest.Id.ToString(); qryParams["ConnectionOpportunityId"] = connectionRequest.ConnectionOpportunityId.ToString(); NavigateToPage( RockPage.Guid, qryParams ); } } }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> public override bool Execute( RockContext rockContext, WorkflowAction action, Object entity, out List<string> errorMessages ) { errorMessages = new List<string>(); var mergeFields = GetMergeFields( action ); // Get the connection request ConnectionRequest request = null; Guid connectionRequestGuid = action.GetWorkflowAttributeValue(GetAttributeValue( action, "ConnectionRequestAttribute" ).AsGuid()).AsGuid(); request = new ConnectionRequestService( rockContext ).Get( connectionRequestGuid ); if ( request == null ) { errorMessages.Add( "Invalid Connection Request Attribute or Value!" ); return false; } // Get the activity type ConnectionActivityType activityType = null; Guid activityTypeGuid = action.GetWorkflowAttributeValue( GetAttributeValue( action, "ConnectionActivityTypeAttribute" ).AsGuid() ).AsGuid(); activityType = new ConnectionActivityTypeService( rockContext ).Get( activityTypeGuid ); if ( activityType == null ) { errorMessages.Add( "Invalid Connection Activity Type Attribute or Value!" ); return false; } // Get the note string noteValue = GetAttributeValue( action, "Note", true ); string note = string.Empty; Guid? noteGuid = noteValue.AsGuidOrNull(); if ( noteGuid.HasValue ) { var attribute = AttributeCache.Get( noteGuid.Value, rockContext ); if ( attribute != null ) { note = action.GetWorkflowAttributeValue( noteGuid.Value ); } } else { note = noteValue; } // Get the connector int? personAliasId = null; Guid? personAttributeGuid = GetAttributeValue( action, "PersonAttribute" ).AsGuidOrNull(); if ( personAttributeGuid.HasValue ) { Guid? personAliasGuid = action.GetWorkflowAttributeValue( personAttributeGuid.Value ).AsGuidOrNull(); if ( personAliasGuid.HasValue ) { var personAlias = new PersonAliasService( rockContext ).Get( personAliasGuid.Value ); if ( personAlias != null ) { personAliasId = personAlias.Id; } } } // Add the activity var activity = new ConnectionRequestActivity(); activity.ConnectionRequestId = request.Id; activity.ConnectionActivityTypeId = activityType.Id; activity.ConnectionOpportunityId = request.ConnectionOpportunityId; activity.ConnectorPersonAliasId = personAliasId; activity.Note = note.ResolveMergeFields( mergeFields ); var connectionRequestActivityService = new ConnectionRequestActivityService( rockContext ); connectionRequestActivityService.Add( activity ); rockContext.SaveChanges(); // If request activity attribute was specified, requery the request and set the attribute's value Guid? connectionRequestActivityAttributeGuid = GetAttributeValue( action, "ConnectionRequestActivityAttribute" ).AsGuidOrNull(); if ( connectionRequestActivityAttributeGuid.HasValue ) { activity = connectionRequestActivityService.Get( activity.Id ); if ( activity != null ) { SetWorkflowAttributeValue( action, connectionRequestActivityAttributeGuid.Value, activity.Guid.ToString() ); } } return true; }
/// <summary> /// Handles the Click event of the lbConnect control. /// </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 lbConnect_Click( object sender, EventArgs e ) { using ( var rockContext = new RockContext() ) { var connectionRequestService = new ConnectionRequestService( rockContext ); var groupMemberService = new GroupMemberService( rockContext ); var connectionActivityTypeService = new ConnectionActivityTypeService( rockContext ); var connectionRequestActivityService = new ConnectionRequestActivityService( rockContext ); var connectionRequest = connectionRequestService.Get( hfConnectionRequestId.ValueAsInt() ); if ( connectionRequest != null && connectionRequest.PersonAlias != null && connectionRequest.ConnectionOpportunity != null ) { // Only do group member placement if the request has an assigned placement group if ( connectionRequest.ConnectionOpportunity.GroupMemberRoleId.HasValue && connectionRequest.AssignedGroupId.HasValue ) { // Only attempt the add if person does not already exist in group with same role var groupMember = groupMemberService.GetByGroupIdAndPersonIdAndGroupRoleId( connectionRequest.AssignedGroupId.Value, connectionRequest.PersonAlias.PersonId, connectionRequest.ConnectionOpportunity.GroupMemberRoleId.Value ); if ( groupMember == null ) { groupMember = new GroupMember(); groupMember.PersonId = connectionRequest.PersonAlias.PersonId; groupMember.GroupRoleId = connectionRequest.ConnectionOpportunity.GroupMemberRoleId.Value; groupMember.GroupMemberStatus = connectionRequest.ConnectionOpportunity.GroupMemberStatus; groupMember.GroupId = connectionRequest.AssignedGroupId.Value; groupMemberService.Add( groupMember ); } } // ... but always record the connection activity and change the state to connected. var guid = Rock.SystemGuid.ConnectionActivityType.CONNECTED.AsGuid(); var connectedActivityId = connectionActivityTypeService.Queryable() .Where( t => t.Guid == guid ) .Select( t => t.Id ) .FirstOrDefault(); if ( connectedActivityId > 0 ) { var connectionRequestActivity = new ConnectionRequestActivity(); connectionRequestActivity.ConnectionRequestId = connectionRequest.Id; connectionRequestActivity.ConnectionOpportunityId = connectionRequest.ConnectionOpportunityId; connectionRequestActivity.ConnectionActivityTypeId = connectedActivityId; connectionRequestActivity.ConnectorPersonAliasId = CurrentPersonAliasId; connectionRequestActivityService.Add( connectionRequestActivity ); } connectionRequest.ConnectionState = ConnectionState.Connected; rockContext.SaveChanges(); ShowDetail( connectionRequest.Id, connectionRequest.ConnectionOpportunityId ); } } }
/// <summary> /// Add Connection Request to Context /// </summary> /// <param name="entityItemPersonAlias">The entity set item person alias.</param> /// <param name="requestCommentsLavaTemplate">The connection opportunity.</param> /// <param name="connectionOpportunityId">The connection opportunity indentifier.</param> /// <param name="connectionStatusId">The connection status identifier.</param> /// <param name="connectorPersonAliasId">The connector person alias indentifier.</param> /// <param name="rockContext">The rock context.</param> /// <returns></returns> private void CreateConnectionRequest(PersonAlias entityItemPersonAlias, string requestCommentsLavaTemplate, int connectionOpportunityId, int?connectionStatusId, int?connectorPersonAliasId, RockContext rockContext) { var defaultCampus = entityItemPersonAlias.Person.GetCampus(); 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(entityItemPersonAlias.PersonId); var connectionRequestActivityService = new ConnectionRequestActivityService(insertRockContext); var insertConnectionRequestService = new ConnectionRequestService(insertRockContext); var connectionRequest = new ConnectionRequest() { ConnectionOpportunityId = connectionOpportunityId, PersonAlias = personPrimaryAlias, ConnectionState = ConnectionState.Active, ConnectorPersonAliasId = connectorPersonAliasId, CampusId = defaultCampus?.Id, ConnectionStatusId = connectionStatusId.Value, }; if (requestCommentsLavaTemplate.IsNotNullOrWhiteSpace()) { var mergeFields = new Dictionary <string, object>(); mergeFields.Add("Person", entityItemPersonAlias.Person); mergeFields.Add("Family", entityItemPersonAlias.Person.GetFamily()); connectionRequest.Comments = 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:{entityItemPersonAlias.Id}.", ex); createConnectionRequestExceptions.Add(exception); ExceptionLogService.LogException(exception, null); } } }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages) { errorMessages = new List <string>(); var mergeFields = GetMergeFields(action); // Get the connection request ConnectionRequest connectionRequest = null; Guid connectionRequestGuid = action.GetWorklowAttributeValue(GetAttributeValue(action, "ConnectionRequestAttribute").AsGuid()).AsGuid(); connectionRequest = new ConnectionRequestService(rockContext).Get(connectionRequestGuid); if (connectionRequest == null) { errorMessages.Add("Invalid Connection Request Attribute or Value!"); return(false); } // Get the connector int? personAliasId = null; Guid?personAttributeGuid = GetAttributeValue(action, "PersonAttribute").AsGuidOrNull(); if (personAttributeGuid.HasValue) { Guid?personAliasGuid = action.GetWorklowAttributeValue(personAttributeGuid.Value).AsGuidOrNull(); if (personAliasGuid.HasValue) { var personAlias = new PersonAliasService(rockContext).Get(personAliasGuid.Value); if (personAlias != null) { personAliasId = personAlias.Id; } } else { errorMessages.Add("Invalid Person Attribute or Value!"); return(false); } } // Set the connector to the connection if (!connectionRequest.ConnectorPersonAliasId.HasValue || !GetAttributeValue(action, "Ignore").AsBoolean()) { int?oldConnectorPersonAliasId = connectionRequest.ConnectorPersonAliasId; int?newConnectorPersonAliasId = personAliasId; connectionRequest.ConnectorPersonAliasId = newConnectorPersonAliasId; rockContext.SaveChanges(); if (newConnectorPersonAliasId.HasValue && !newConnectorPersonAliasId.Equals(oldConnectorPersonAliasId)) { var guid = Rock.SystemGuid.ConnectionActivityType.ASSIGNED.AsGuid(); var assignedActivityId = new ConnectionActivityTypeService(rockContext).Queryable() .Where(t => t.Guid == guid) .Select(t => t.Id) .FirstOrDefault(); if (assignedActivityId > 0) { var connectionRequestActivityService = new ConnectionRequestActivityService(rockContext); var connectionRequestActivity = new ConnectionRequestActivity(); connectionRequestActivity.ConnectionRequestId = connectionRequest.Id; connectionRequestActivity.ConnectionOpportunityId = connectionRequest.ConnectionOpportunityId; connectionRequestActivity.ConnectionActivityTypeId = assignedActivityId; connectionRequestActivity.ConnectorPersonAliasId = newConnectorPersonAliasId; connectionRequestActivityService.Add(connectionRequestActivity); rockContext.SaveChanges(); } } } return(true); }
/// <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); }