/// <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>(); string filename = GetAttributeValue(action, "FileName"); filename = filename.ResolveMergeFields(GetMergeFields(action)); if (string.IsNullOrWhiteSpace(filename)) { filename = "file.txt"; } string mimeType = GetAttributeValue(action, "MimeType"); mimeType = mimeType.ResolveMergeFields(GetMergeFields(action)); if (string.IsNullOrWhiteSpace(mimeType)) { mimeType = "text/plain"; } Guid guid = GetAttributeValue(action, "ResultAttribute").AsGuid(); if (!guid.IsEmpty()) { var destinationAttribute = AttributeCache.Get(guid, rockContext); if (destinationAttribute != null) { string lavaTemplate = GetAttributeValue(action, "LavaTemplate"); // determine binary file type to use for storing the file Guid binaryFileTypeGuid = Guid.Empty; var binaryFileTypeQualifier = destinationAttribute.QualifierValues["binaryFileType"]; if (binaryFileTypeQualifier != null) { if (binaryFileTypeQualifier.Value != null) { binaryFileTypeGuid = binaryFileTypeQualifier.Value.AsGuid(); } } if (binaryFileTypeGuid == Guid.Empty) { binaryFileTypeGuid = Rock.SystemGuid.BinaryFiletype.DEFAULT.AsGuid(); } int binaryFileTypeId = new BinaryFileTypeService(rockContext).Get(binaryFileTypeGuid).Id; // merge lava to text content var lavaOutput = lavaTemplate.ResolveMergeFields(GetMergeFields(action)); // convert lava to text using (Stream fileOutput = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(lavaOutput))) { // save output to binary file var binaryFileService = new BinaryFileService(rockContext); var binaryFile = new BinaryFile(); binaryFileService.Add(binaryFile); binaryFile.BinaryFileTypeId = binaryFileTypeId; binaryFile.MimeType = mimeType; binaryFile.FileName = filename; binaryFile.ContentStream = fileOutput; rockContext.SaveChanges(); if (destinationAttribute.EntityTypeId == new Rock.Model.Workflow().TypeId) { action.Activity.Workflow.SetAttributeValue(destinationAttribute.Key, binaryFile.Guid.ToString()); action.AddLogEntry(string.Format("Set '{0}' attribute to '{1}'.", destinationAttribute.Name, lavaOutput)); } else if (destinationAttribute.EntityTypeId == new Rock.Model.WorkflowActivity().TypeId) { action.Activity.SetAttributeValue(destinationAttribute.Key, binaryFile.Guid.ToString()); action.AddLogEntry(string.Format("Set '{0}' attribute to '{1}'.", destinationAttribute.Name, lavaOutput)); } } } } errorMessages.ForEach(m => action.AddLogEntry(m, true)); return(true); }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The workflow action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public override bool Execute(RockContext rockContext, Model.WorkflowAction action, Object entity, out List <string> errorMessages) { var checkInState = GetCheckInState(entity, out errorMessages); if (checkInState != null && checkInState.CheckIn.SearchType != null) { checkInState.CheckIn.Families = new List <CheckInFamily>(); if (!string.IsNullOrWhiteSpace(checkInState.CheckIn.SearchValue)) { var personService = new PersonService(rockContext); var memberService = new GroupMemberService(rockContext); var groupService = new GroupService(rockContext); int personRecordTypeId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid()).Id; int familyGroupTypeId = GroupTypeCache.Get(Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid()).Id; var dvInactive = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_INACTIVE.AsGuid()); IQueryable <int> familyIdQry = null; if (checkInState.CheckIn.SearchType.Guid.Equals(SystemGuid.DefinedValue.CHECKIN_SEARCH_TYPE_PHONE_NUMBER.AsGuid())) { string numericPhone = checkInState.CheckIn.SearchValue.AsNumeric(); var phoneQry = new PhoneNumberService(rockContext).Queryable().AsNoTracking(); if (checkInState.CheckInType == null || checkInState.CheckInType.PhoneSearchType == PhoneSearchType.EndsWith) { char[] charArray = numericPhone.ToCharArray(); Array.Reverse(charArray); phoneQry = phoneQry.Where(o => o.NumberReversed.StartsWith(new string( charArray ))); } else { phoneQry = phoneQry.Where(o => o.Number.Contains(numericPhone)); } var tmpQry = phoneQry.Join(personService.Queryable().AsNoTracking(), o => new { PersonId = o.PersonId, IsDeceased = false, RecordTypeValueId = personRecordTypeId }, p => new { PersonId = p.Id, IsDeceased = p.IsDeceased, RecordTypeValueId = p.RecordTypeValueId.Value }, (pn, p) => new { Person = p, PhoneNumber = pn }) .Join(memberService.Queryable().AsNoTracking(), pn => pn.Person.Id, m => m.PersonId, (o, m) => new { PersonNumber = o.PhoneNumber, GroupMember = m }); familyIdQry = groupService.Queryable().Where(g => tmpQry.Any(o => o.GroupMember.GroupId == g.Id) && g.GroupTypeId == familyGroupTypeId) .Select(g => g.Id) .Distinct(); } else { var familyMemberQry = memberService .AsNoFilter().AsNoTracking() .Where(m => m.Group.GroupTypeId == familyGroupTypeId && m.Person.RecordTypeValueId == personRecordTypeId); if (checkInState.CheckIn.SearchType.Guid.Equals(SystemGuid.DefinedValue.CHECKIN_SEARCH_TYPE_NAME.AsGuid())) { var personIds = personService.GetByFullName(checkInState.CheckIn.SearchValue, false).AsNoTracking().Select(p => p.Id); familyMemberQry = familyMemberQry.Where(f => personIds.Contains(f.PersonId)); } else if (checkInState.CheckIn.SearchType.Guid.Equals(SystemGuid.DefinedValue.CHECKIN_SEARCH_TYPE_SCANNED_ID.AsGuid())) { var personIds = new List <int>(); var dv = DefinedValueCache.Get(SystemGuid.DefinedValue.PERSON_SEARCH_KEYS_ALTERNATE_ID.AsGuid()); if (dv != null) { var searchValueService = new PersonSearchKeyService(rockContext); var personAliases = searchValueService.Queryable().AsNoTracking() .Where(v => v.SearchTypeValueId == dv.Id && v.SearchValue == checkInState.CheckIn.SearchValue) .Select(v => v.PersonAlias); if (personAliases.Any()) { checkInState.CheckIn.CheckedInByPersonAliasId = personAliases.First().Id; personIds = personAliases.Select(a => a.PersonId).ToList(); } } if (personIds.Any()) { familyMemberQry = familyMemberQry.Where(f => personIds.Contains(f.PersonId)); } else { // if there were no matches, try to find a family check-in identifier. V8 has a "run once" job that moves the family identifiers // to person search values, but in case the job has not yet completed, will still do the check for family ids. var entityIds = new List <int>(); var attributeValueService = new AttributeValueService(rockContext); var attr = AttributeCache.Get("8F528431-A438-4488-8DC3-CA42E66C1B37".AsGuid()); if (attr != null) { entityIds = new AttributeValueService(rockContext) .Queryable().AsNoTracking() .Where(v => v.AttributeId == attr.Id && v.EntityId.HasValue && ("|" + v.Value + "|").Contains("|" + checkInState.CheckIn.SearchValue + "|")) .Select(v => v.EntityId.Value) .ToList(); } familyMemberQry = familyMemberQry.Where(f => entityIds.Contains(f.GroupId)); } } else if (checkInState.CheckIn.SearchType.Guid.Equals(SystemGuid.DefinedValue.CHECKIN_SEARCH_TYPE_FAMILY_ID.AsGuid())) { List <int> searchFamilyIds = checkInState.CheckIn.SearchValue.SplitDelimitedValues().AsIntegerList(); familyMemberQry = familyMemberQry.Where(f => searchFamilyIds.Contains(f.GroupId)); } else { errorMessages.Add("Invalid Search Type"); return(false); } familyIdQry = familyMemberQry .Select(m => m.GroupId) .Distinct(); } int maxResults = checkInState.CheckInType != null ? checkInState.CheckInType.MaxSearchResults : 100; if (maxResults > 0) { familyIdQry = familyIdQry.Take(maxResults); } // You might think we should do a ToList() on the familyIdQry and use it below, // but through some extensive testing, we discovered that the next SQL query is better // optimized if it has the familyIdQry without being to-listed. It was over 270% slower // when querying names and 120% slower when querying phone numbers. // Load the family members var familyMembers = memberService .Queryable().AsNoTracking() .Where(m => m.Group.GroupTypeId == familyGroupTypeId && familyIdQry.Contains(m.GroupId)).Select(a => new { Group = a.Group, GroupId = a.GroupId, Order = a.GroupRole.Order, BirthYear = a.Person.BirthYear, BirthMonth = a.Person.BirthMonth, BirthDay = a.Person.BirthDay, Gender = a.Person.Gender, NickName = a.Person.NickName, RecordStatusValueId = a.Person.RecordStatusValueId }) .ToList(); // Add each family foreach (int familyId in familyMembers.Select(fm => fm.GroupId).Distinct()) { // Get each of the members for this family var familyMemberQry = familyMembers .Where(m => m.GroupId == familyId && m.NickName != null); if (checkInState.CheckInType != null && checkInState.CheckInType.PreventInactivePeople && dvInactive != null) { familyMemberQry = familyMemberQry .Where(m => m.RecordStatusValueId != dvInactive.Id); } var thisFamilyMembers = familyMemberQry.ToList(); if (thisFamilyMembers.Any()) { var group = thisFamilyMembers .Select(m => m.Group) .FirstOrDefault(); var firstNames = thisFamilyMembers .OrderBy(m => m.Order) .ThenBy(m => m.BirthYear) .ThenBy(m => m.BirthMonth) .ThenBy(m => m.BirthDay) .ThenBy(m => m.Gender) .Select(m => m.NickName) .ToList(); var family = new CheckInFamily(); family.Group = group.Clone(false); family.Caption = group.ToString(); family.FirstNames = firstNames; family.SubCaption = firstNames.AsDelimited(", "); checkInState.CheckIn.Families.Add(family); } } } return(true); } errorMessages.Add("Invalid Check-in State"); return(false); }
private void SaveAttendance(Group group, Location location, Schedule schedule) { PersonAliasService personAliasService = new PersonAliasService(rockContext); var personAlias = personAliasService.Get(personAliasGuid.AsGuid()); if (personAlias == null) { errorMessages.Add("No Person Found"); return; } ; var memberOptions = keywordSearchType = GetAttributeValue(action, "MemberOptions", true); if (memberOptions != "0") //Not just add attendance { GroupMemberService groupMemberService = new GroupMemberService(rockContext); // get group member var groupMember = groupMemberService.Queryable() .Where(m => m.GroupId == group.Id && m.PersonId == personAlias.PersonId) .FirstOrDefault(); if (groupMember == null) { if (memberOptions == "1") //Create new member { if (group != null) { groupMember = new GroupMember(); groupMember.GroupId = group.Id; groupMember.PersonId = personAlias.PersonId; groupMember.GroupMemberStatus = GroupMemberStatus.Active; groupMember.GroupRole = group.GroupType.DefaultGroupRole; groupMemberService.Add(groupMember); rockContext.SaveChanges(); } } else //Must be in group { action.AddLogEntry(string.Format("{0} was not a member of the group {1} and the action was not configured to add them.", personAlias.Person.FullName, group.Name)); return; } } } //Save attendance AttendanceService attendanceService = new AttendanceService(rockContext); attendanceService.AddOrUpdate(personAlias.Id, Rock.RockDateTime.Now, group.Id, location?.Id, schedule?.Id, location?.CampusId); //Set Attributes for Group Location and Schedule var groupAttribute = AttributeCache.Get(GetAttributeValue(action, "GroupOutput").AsGuid(), rockContext); if (groupAttribute != null) { SetWorkflowAttributeValue(action, groupAttribute.Guid, group.Guid.ToString()); } var locationAttribute = AttributeCache.Get(GetAttributeValue(action, "LocationOutput").AsGuid(), rockContext); if (locationAttribute != null && location != null) { SetWorkflowAttributeValue(action, locationAttribute.Guid, location.Guid.ToString()); } var scheduleAttribute = AttributeCache.Get(GetAttributeValue(action, "ScheduleOutput").AsGuid(), rockContext); if (scheduleAttribute != null && schedule != null) { SetWorkflowAttributeValue(action, scheduleAttribute.Guid, schedule.Guid.ToString()); } }
/// <summary> /// Sets the filters. /// </summary> private void SetFilters(bool setValues) { using (var rockContext = new RockContext()) { string sessionKey = string.Format("ConnectionSearch_{0}", this.BlockId); var searchSelections = Session[sessionKey] as Dictionary <string, string>; setValues = setValues && searchSelections != null; var connectionType = new ConnectionTypeService(rockContext).Get(GetAttributeValue("ConnectionTypeId").AsInteger()); if (!GetAttributeValue("DisplayNameFilter").AsBoolean()) { tbSearchName.Visible = false; } if (GetAttributeValue("DisplayCampusFilter").AsBoolean()) { cblCampus.Visible = true; cblCampus.DataSource = CampusCache.All().Where(c => c.AttributeValues["Public"].ToString().AsBoolean() == true); cblCampus.DataBind(); } else { cblCampus.Visible = false; } if (setValues) { if (searchSelections.ContainsKey("tbSearchName")) { tbSearchName.Text = searchSelections["tbSearchName"]; } if (searchSelections.ContainsKey("cblCampus")) { var selectedItems = searchSelections["cblCampus"].SplitDelimitedValues().AsIntegerList(); cblCampus.SetValues(selectedItems); } } else if (GetAttributeValue("EnableCampusContext").AsBoolean()) { var campusEntityType = EntityTypeCache.Get("Rock.Model.Campus"); var contextCampus = RockPage.GetCurrentContext(campusEntityType) as Campus; if (contextCampus != null) { cblCampus.SetValue(contextCampus.Id.ToString()); } } if (GetAttributeValue("DisplayAttributeFilters").AsBoolean()) { // Parse the attribute filters AvailableAttributes = new List <AttributeCache>(); if (connectionType != null) { int entityTypeId = new ConnectionOpportunity().TypeId; foreach (var attributeModel in new AttributeService(new RockContext()).Queryable() .Where(a => a.EntityTypeId == entityTypeId && a.EntityTypeQualifierColumn.Equals("ConnectionTypeId", StringComparison.OrdinalIgnoreCase) && a.EntityTypeQualifierValue.Equals(connectionType.Id.ToString()) && a.AllowSearch == true) .OrderBy(a => a.Order) .ThenBy(a => a.Name)) { AvailableAttributes.Add(AttributeCache.Get(attributeModel)); } } // Clear the filter controls phAttributeFilters.Controls.Clear(); if (AvailableAttributes != null) { foreach (var attribute in AvailableAttributes) { string controlId = "filter_" + attribute.Id.ToString(); var control = attribute.FieldType.Field.FilterControl(attribute.QualifierValues, controlId, false, Rock.Reporting.FilterMode.SimpleFilter); if (control != null) { if (control is IRockControl) { var rockControl = ( IRockControl )control; rockControl.Label = attribute.Name; rockControl.Help = attribute.Description; phAttributeFilters.Controls.Add(control); } else { var wrapper = new RockControlWrapper(); wrapper.ID = control.ID + "_wrapper"; wrapper.Label = attribute.Name; wrapper.Controls.Add(control); phAttributeFilters.Controls.Add(wrapper); } if (setValues && searchSelections.ContainsKey(controlId)) { var values = searchSelections[controlId].FromJsonOrNull <List <string> >(); attribute.FieldType.Field.SetFilterValues(control, attribute.QualifierValues, values); } } } } } else { phAttributeFilters.Visible = false; } } }
/// <summary> /// Handles the Click event of the btnSaveEditPreferences 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 btnSaveEditPreferences_Click(object sender, EventArgs e) { var rockContext = new RockContext(); var groupMember = new GroupMemberService(rockContext).Get(hfGroupMemberId.Value.AsInteger()); var personService = new PersonService(rockContext); var person = personService.Get(groupMember.PersonId); int?orphanedPhotoId = null; if (person.PhotoId != imgProfilePhoto.BinaryFileId) { orphanedPhotoId = person.PhotoId; person.PhotoId = imgProfilePhoto.BinaryFileId; // add or update the Photo Verify group to have this person as Pending since the photo was changed or deleted using (var photoRequestRockContext = new RockContext()) { GroupMemberService groupMemberService = new GroupMemberService(photoRequestRockContext); Group photoRequestGroup = new GroupService(photoRequestRockContext).Get(Rock.SystemGuid.Group.GROUP_PHOTO_REQUEST.AsGuid()); var photoRequestGroupMember = groupMemberService.Queryable().Where(a => a.GroupId == photoRequestGroup.Id && a.PersonId == person.Id).FirstOrDefault(); if (photoRequestGroupMember == null) { photoRequestGroupMember = new GroupMember(); photoRequestGroupMember.GroupId = photoRequestGroup.Id; photoRequestGroupMember.PersonId = person.Id; photoRequestGroupMember.GroupRoleId = photoRequestGroup.GroupType.DefaultGroupRoleId ?? -1; groupMemberService.Add(photoRequestGroupMember); } photoRequestGroupMember.GroupMemberStatus = GroupMemberStatus.Pending; photoRequestRockContext.SaveChanges(); } } // Save the GroupMember Attributes groupMember.LoadAttributes(); Rock.Attribute.Helper.GetEditValues(phGroupMemberAttributes, groupMember); // Save selected Person Attributes (The ones picked in Block Settings) var personAttributes = this.GetAttributeValue("PersonAttributes").SplitDelimitedValues().AsGuidList().Select(a => AttributeCache.Get(a)); if (personAttributes.Any()) { person.LoadAttributes(rockContext); foreach (var personAttribute in personAttributes) { Control attributeControl = phPersonAttributes.FindControl(string.Format("attribute_field_{0}", personAttribute.Id)); if (attributeControl != null) { // Save Attribute value to the database string newValue = personAttribute.FieldType.Field.GetEditValue(attributeControl, personAttribute.QualifierValues); Rock.Attribute.Helper.SaveAttributeValue(person, personAttribute, newValue, rockContext); } } } // Save everything else to the database in a db transaction rockContext.WrapTransaction(() => { rockContext.SaveChanges(); groupMember.SaveAttributeValues(rockContext); if (orphanedPhotoId.HasValue) { BinaryFileService binaryFileService = new BinaryFileService(rockContext); var binaryFile = binaryFileService.Get(orphanedPhotoId.Value); if (binaryFile != null) { // marked the old images as IsTemporary so they will get cleaned up later binaryFile.IsTemporary = true; rockContext.SaveChanges(); } } // if they used the ImageEditor, and cropped it, the uncropped file is still in BinaryFile. So clean it up if (imgProfilePhoto.CropBinaryFileId.HasValue) { if (imgProfilePhoto.CropBinaryFileId != person.PhotoId) { BinaryFileService binaryFileService = new BinaryFileService(rockContext); var binaryFile = binaryFileService.Get(imgProfilePhoto.CropBinaryFileId.Value); if (binaryFile != null && binaryFile.IsTemporary) { string errorMessage; if (binaryFileService.CanDelete(binaryFile, out errorMessage)) { binaryFileService.Delete(binaryFile); rockContext.SaveChanges(); } } } } }); ShowView(hfGroupId.Value.AsInteger(), hfGroupMemberId.Value.AsInteger()); }
private void Map() { string mapStylingFormat = @" <style> #map_wrapper {{ height: {0}px; }} #map_canvas {{ width: 100%; height: 100%; border-radius: var(--border-radius-base); }} </style>"; lMapStyling.Text = string.Format(mapStylingFormat, GetAttributeValue("MapHeight")); string settingGroupTypeId = GetAttributeValue("GroupType"); string queryStringGroupTypeId = PageParameter("GroupTypeId"); if ((string.IsNullOrWhiteSpace(settingGroupTypeId) && string.IsNullOrWhiteSpace(queryStringGroupTypeId))) { pnlMap.Visible = false; lMessages.Text = "<div class='alert alert-warning'><strong>Group Mapper</strong> Please configure a group type to display as a block setting or pass a GroupTypeId as a query parameter.</div>"; } else { var rockContext = new RockContext(); pnlMap.Visible = true; int groupsMapped = 0; int groupsWithNoGeo = 0; StringBuilder sbGroupJson = new StringBuilder(); StringBuilder sbGroupsWithNoGeo = new StringBuilder(); Guid?groupType = null; int groupTypeId = -1; if (!string.IsNullOrWhiteSpace(settingGroupTypeId)) { groupType = new Guid(settingGroupTypeId); } else { if (!string.IsNullOrWhiteSpace(queryStringGroupTypeId) && Int32.TryParse(queryStringGroupTypeId, out groupTypeId)) { groupType = new GroupTypeService(rockContext).Get(groupTypeId).Guid; } } if (groupType != null) { Template template = null; if (GetAttributeValue("ShowMapInfoWindow").AsBoolean()) { template = Template.Parse(GetAttributeValue("InfoWindowContents").Trim()); } else { template = Template.Parse(string.Empty); } var groupPageRef = new PageReference(GetAttributeValue("GroupDetailPage")); // create group detail link for use in map's info window var personPageParams = new Dictionary <string, string>(); personPageParams.Add("PersonId", string.Empty); var personProfilePage = LinkedPageUrl("PersonProfilePage", personPageParams); var groupEntityType = EntityTypeCache.Get(typeof(Group)); var dynamicGroups = new List <dynamic>(); // Create query to get attribute values for selected attribute keys. var attributeKeys = GetAttributeValue("Attributes").SplitDelimitedValues().ToList(); var attributeValues = new AttributeValueService(rockContext).Queryable("Attribute") .Where(v => v.Attribute.EntityTypeId == groupEntityType.Id && attributeKeys.Contains(v.Attribute.Key)); GroupService groupService = new GroupService(rockContext); var groups = groupService.Queryable() .Where(g => g.GroupType.Guid == groupType) .Select(g => new { Group = g, GroupId = g.Id, GroupName = g.Name, GroupGuid = g.Guid, GroupMemberTerm = g.GroupType.GroupMemberTerm, GroupCampus = g.Campus.Name, IsActive = g.IsActive, GroupLocation = g.GroupLocations .Where(l => l.Location.GeoPoint != null) .Select(l => new { l.Location.Street1, l.Location.Street2, l.Location.City, l.Location.State, PostalCode = l.Location.PostalCode, Latitude = l.Location.GeoPoint.Latitude, Longitude = l.Location.GeoPoint.Longitude, Name = l.GroupLocationTypeValue.Value }).FirstOrDefault(), GroupMembers = g.Members, AttributeValues = attributeValues .Where(v => v.EntityId == g.Id) }); if (GetAttributeValue("IncludeInactiveGroups").AsBoolean() == false) { groups = groups.Where(g => g.IsActive == true); } // Create dynamic object to include attribute values foreach (var group in groups) { dynamic dynGroup = new ExpandoObject(); dynGroup.GroupId = group.GroupId; dynGroup.GroupName = group.GroupName; // create group detail link for use in map's info window if (groupPageRef.PageId > 0) { var groupPageParams = new Dictionary <string, string>(); groupPageParams.Add("GroupId", group.GroupId.ToString()); groupPageRef.Parameters = groupPageParams; dynGroup.GroupDetailPage = groupPageRef.BuildUrl(); } else { dynGroup.GroupDetailPage = string.Empty; } dynGroup.PersonProfilePage = personProfilePage; dynGroup.GroupMemberTerm = group.GroupMemberTerm; dynGroup.GroupCampus = group.GroupCampus; dynGroup.GroupLocation = group.GroupLocation; var groupAttributes = new List <dynamic>(); foreach (AttributeValue value in group.AttributeValues) { var attrCache = AttributeCache.Get(value.AttributeId); var dictAttribute = new Dictionary <string, object>(); dictAttribute.Add("Key", attrCache.Key); dictAttribute.Add("Name", attrCache.Name); if (attrCache != null) { dictAttribute.Add("Value", attrCache.FieldType.Field.FormatValueAsHtml(null, attrCache.EntityTypeId, group.GroupId, value.Value, attrCache.QualifierValues, false)); } else { dictAttribute.Add("Value", value.Value); } groupAttributes.Add(dictAttribute); } dynGroup.Attributes = groupAttributes; var groupMembers = new List <dynamic>(); foreach (GroupMember member in group.GroupMembers) { var dictMember = new Dictionary <string, object>(); dictMember.Add("Id", member.Person.Id); dictMember.Add("GuidP", member.Person.Guid); dictMember.Add("NickName", member.Person.NickName); dictMember.Add("LastName", member.Person.LastName); dictMember.Add("RoleName", member.GroupRole.Name); dictMember.Add("Email", member.Person.Email); dictMember.Add("PhotoGuid", member.Person.Photo != null ? member.Person.Photo.Guid : Guid.Empty); var phoneTypes = new List <dynamic>(); foreach (PhoneNumber p in member.Person.PhoneNumbers) { var dictPhoneNumber = new Dictionary <string, object>(); dictPhoneNumber.Add("Name", p.NumberTypeValue.Value); dictPhoneNumber.Add("Number", p.ToString()); phoneTypes.Add(dictPhoneNumber); } dictMember.Add("PhoneTypes", phoneTypes); groupMembers.Add(dictMember); } dynGroup.GroupMembers = groupMembers; dynamicGroups.Add(dynGroup); } foreach (var group in dynamicGroups) { if (group.GroupLocation != null && group.GroupLocation.Latitude != null) { groupsMapped++; var groupDict = group as IDictionary <string, object>; string infoWindow = template.Render(Hash.FromDictionary(groupDict)).Replace("\n", string.Empty); sbGroupJson.Append(string.Format( @"{{ ""name"":""{0}"" , ""latitude"":""{1}"", ""longitude"":""{2}"", ""infowindow"":""{3}"" }},", HttpUtility.HtmlEncode(group.GroupName), group.GroupLocation.Latitude, group.GroupLocation.Longitude, HttpUtility.HtmlEncode(infoWindow))); } else { groupsWithNoGeo++; if (!string.IsNullOrWhiteSpace(group.GroupDetailPage)) { sbGroupsWithNoGeo.Append(string.Format(@"<li><a href='{0}'>{1}</a></li>", group.GroupDetailPage, group.GroupName)); } else { sbGroupsWithNoGeo.Append(string.Format(@"<li>{0}</li>", group.GroupName)); } } } string groupJson = sbGroupJson.ToString(); // remove last comma if (groupJson.Length > 0) { groupJson = groupJson.Substring(0, groupJson.Length - 1); } // add styling to map string styleCode = "null"; string markerColor = "FE7569"; DefinedValueCache dvcMapStyle = DefinedValueCache.Get(GetAttributeValue("MapStyle").AsGuid()); if (dvcMapStyle != null) { styleCode = dvcMapStyle.GetAttributeValue("DynamicMapStyle"); var colors = dvcMapStyle.GetAttributeValue("Colors").Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList(); if (colors.Any()) { markerColor = colors.First().Replace("#", ""); } } // write script to page string mapScriptFormat = @" <script> Sys.Application.add_load(function () {{ var groupData = JSON.parse('{{ ""groups"" : [ {0} ]}}'); var showInfoWindow = {1}; var mapStyle = {2}; var pinColor = '{3}'; var pinImage = {{ path: 'M 0,0 C -2,-20 -10,-22 -10,-30 A 10,10 0 1,1 10,-30 C 10,-22 2,-20 0,0 z', fillColor: '#' + pinColor, fillOpacity: 1, strokeColor: '#000', strokeWeight: 1, scale: 1, labelOrigin: new google.maps.Point(0,-28) }}; initializeMap(); function initializeMap() {{ console.log(mapStyle); var map; var bounds = new google.maps.LatLngBounds(); var mapOptions = {{ mapTypeId: 'roadmap', styles: mapStyle }}; // Display a map on the page map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions); map.setTilt(45); // Display multiple markers on a map if (showInfoWindow) {{ var infoWindow = new google.maps.InfoWindow(), marker, i; }} // Loop through our array of markers & place each one on the map $.each(groupData.groups, function (i, group) {{ var position = new google.maps.LatLng(group.latitude, group.longitude); bounds.extend(position); marker = new google.maps.Marker({{ position: position, map: map, title: htmlDecode(group.name), icon: pinImage, label: String.fromCharCode(9679) }}); // Allow each marker to have an info window if (showInfoWindow) {{ google.maps.event.addListener(marker, 'click', (function (marker, i) {{ return function () {{ infoWindow.setContent(htmlDecode(groupData.groups[i].infowindow)); infoWindow.open(map, marker); }} }})(marker, i)); }} map.fitBounds(bounds); }}); // Override our map zoom level once our fitBounds function runs (Make sure it only runs once) var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function (event) {{ google.maps.event.removeListener(boundsListener); }}); }} function htmlDecode(input) {{ var e = document.createElement('div'); e.innerHTML = input; return e.childNodes.length === 0 ? """" : e.childNodes[0].nodeValue; }} }}); </script>"; string mapScript = string.Format( mapScriptFormat, groupJson, GetAttributeValue("ShowMapInfoWindow").AsBoolean().ToString().ToLower(), styleCode, markerColor); ScriptManager.RegisterStartupScript(pnlMap, pnlMap.GetType(), "group-mapper-script", mapScript, false); if (groupsMapped == 0) { pnlMap.Visible = false; lMessages.Text = @" <p> <div class='alert alert-warning fade in'>No groups were able to be mapped. You may want to check your configuration.</div> </p>"; } else { // output any warnings if (groupsWithNoGeo > 0) { string messagesFormat = @" <p> <div class='alert alert-warning fade in'>Some groups could not be mapped. <button type='button' class='close' data-dismiss='alert' aria-hidden='true'><i class='fa fa-times'></i></button> <small><a data-toggle='collapse' data-parent='#accordion' href='#map-error-details'>Show Details</a></small> <div id='map-error-details' class='collapse'> <p class='margin-t-sm'> <strong>Groups That Could Not Be Mapped</strong> <ul> {0} </ul> </p> </div> </div> </p>"; lMessages.Text = string.Format(messagesFormat, sbGroupsWithNoGeo.ToString()); } } } else { pnlMap.Visible = false; lMessages.Text = "<div class='alert alert-warning'><strong>Group Mapper</strong> Please configure a group type to display and a location type to use.</div>"; } } }
/// <summary> /// Binds the grid. /// </summary> /// <param name="report">The report.</param> /// <param name="gReport">The g report.</param> /// <param name="currentPerson">The current person.</param> /// <param name="dataViewFilterOverrides">The data view filter overrides.</param> /// <param name="databaseTimeoutSeconds">The database timeout seconds.</param> /// <param name="isCommunication">if set to <c>true</c> [is communication].</param> /// <param name="errorMessage">The error message.</param> public static void BindGrid(Report report, Grid gReport, Person currentPerson, DataViewFilterOverrides dataViewFilterOverrides, int?databaseTimeoutSeconds, bool isCommunication, out string errorMessage) { errorMessage = null; if (report != null) { var errors = new List <string>(); if (!report.EntityTypeId.HasValue) { gReport.Visible = false; return; } var rockContext = new RockContext(); if (!report.IsAuthorized(Authorization.VIEW, currentPerson)) { gReport.Visible = false; return; } Type entityType = EntityTypeCache.Get(report.EntityTypeId.Value, rockContext).GetEntityType(); if (entityType == null) { errorMessage = string.Format("Unable to determine entityType for {0}", report.EntityType); return; } gReport.EntityTypeId = report.EntityTypeId; bool isPersonDataSet = report.EntityTypeId == EntityTypeCache.Get(typeof(Rock.Model.Person), true, rockContext).Id; if (isPersonDataSet) { gReport.PersonIdField = "Id"; gReport.DataKeyNames = new string[] { "Id" }; } else { gReport.PersonIdField = null; } if (report.EntityTypeId.HasValue) { gReport.RowItemText = EntityTypeCache.Get(report.EntityTypeId.Value, rockContext).FriendlyName; } List <EntityField> entityFields = Rock.Reporting.EntityHelper.GetEntityFields(entityType, true, false); var selectedEntityFields = new Dictionary <int, EntityField>(); var selectedAttributes = new Dictionary <int, AttributeCache>(); var selectedComponents = new Dictionary <int, ReportField>(); // if there is a selectField, keep it to preserve which items are checked var selectField = gReport.Columns.OfType <SelectField>().FirstOrDefault(); gReport.Columns.Clear(); int columnIndex = 0; if (!string.IsNullOrWhiteSpace(gReport.PersonIdField)) { // if we already had a selectField, use it (to preserve checkbox state) gReport.Columns.Add(selectField ?? new SelectField()); columnIndex++; } var reportFieldSortExpressions = new Dictionary <Guid, string>(); gReport.CommunicateMergeFields = new List <string>(); gReport.CommunicationRecipientPersonIdFields = new List <string>(); foreach (var reportField in report.ReportFields.OrderBy(a => a.ColumnOrder)) { bool mergeField = reportField.IsCommunicationMergeField.HasValue && reportField.IsCommunicationMergeField.Value; bool recipientField = reportField.IsCommunicationRecipientField.HasValue && reportField.IsCommunicationRecipientField.Value; columnIndex++; if (reportField.ReportFieldType == ReportFieldType.Property) { var entityField = entityFields.FirstOrDefault(a => a.Name == reportField.Selection); if (entityField != null) { selectedEntityFields.Add(columnIndex, entityField); BoundField boundField = entityField.GetBoundFieldType(); boundField.DataField = string.Format("Entity_{0}_{1}", entityField.Name, columnIndex); boundField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? entityField.Title : reportField.ColumnHeaderText; boundField.SortExpression = boundField.DataField; reportFieldSortExpressions.AddOrReplace(reportField.Guid, boundField.SortExpression); boundField.Visible = reportField.ShowInGrid; gReport.Columns.Add(boundField); if (mergeField) { gReport.CommunicateMergeFields.Add($"{boundField.DataField}|{boundField.HeaderText.RemoveSpecialCharacters()}"); } if (recipientField) { gReport.CommunicationRecipientPersonIdFields.Add(boundField.DataField); } } } else if (reportField.ReportFieldType == ReportFieldType.Attribute) { Guid?attributeGuid = reportField.Selection.AsGuidOrNull(); if (attributeGuid.HasValue) { var attribute = AttributeCache.Get(attributeGuid.Value, rockContext); if (attribute != null && attribute.IsActive) { selectedAttributes.Add(columnIndex, attribute); BoundField boundField; if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.BOOLEAN.AsGuid())) { boundField = new BoolField(); } else if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.DEFINED_VALUE.AsGuid())) { boundField = new DefinedValueField(); } else { boundField = new CallbackField(); boundField.HtmlEncode = false; (boundField as CallbackField).OnFormatDataValue += (sender, e) => { string resultHtml = null; var attributeValue = e.DataValue ?? attribute.DefaultValueAsType; if (attributeValue != null) { bool condensed = true; resultHtml = attribute.FieldType.Field.FormatValueAsHtml(gReport, attributeValue.ToString(), attribute.QualifierValues, condensed); } e.FormattedValue = resultHtml ?? string.Empty; }; } boundField.DataField = string.Format("Attribute_{0}_{1}", attribute.Id, columnIndex); boundField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? attribute.Name : reportField.ColumnHeaderText; boundField.SortExpression = boundField.DataField; reportFieldSortExpressions.AddOrReplace(reportField.Guid, boundField.SortExpression); if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.INTEGER.AsGuid()) || attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.DATE.AsGuid()) || attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.FILTER_DATE.AsGuid())) { boundField.HeaderStyle.HorizontalAlign = HorizontalAlign.Right; boundField.ItemStyle.HorizontalAlign = HorizontalAlign.Right; } boundField.Visible = reportField.ShowInGrid; gReport.Columns.Add(boundField); if (mergeField) { gReport.CommunicateMergeFields.Add($"{boundField.DataField}|{boundField.HeaderText.RemoveSpecialCharacters()}"); } if (recipientField) { gReport.CommunicationRecipientPersonIdFields.Add(boundField.DataField); } } } } else if (reportField.ReportFieldType == ReportFieldType.DataSelectComponent) { selectedComponents.Add(columnIndex, reportField); DataSelectComponent selectComponent = DataSelectContainer.GetComponent(reportField.DataSelectComponentEntityType.Name); if (selectComponent != null) { try { DataControlField columnField = selectComponent.GetGridField(entityType, reportField.Selection ?? string.Empty); string fieldId = $"{selectComponent.ColumnPropertyName}_{columnIndex}"; if (columnField is BoundField) { (columnField as BoundField).DataField = $"Data_{fieldId}"; var customSortProperties = selectComponent.SortProperties(reportField.Selection ?? string.Empty); bool sortReversed = selectComponent.SortReversed(reportField.Selection ?? string.Empty); if (customSortProperties != null) { if (customSortProperties == string.Empty) { // disable sorting if customSortExpression set to string.empty columnField.SortExpression = string.Empty; } else { columnField.SortExpression = customSortProperties.Split(',').Select(a => string.Format("Sort_{0}_{1}", a, columnIndex)).ToList().AsDelimited(","); } } else { // use default sorting if customSortExpression was null columnField.SortExpression = (columnField as BoundField).DataField; } if (sortReversed == true && !string.IsNullOrWhiteSpace(columnField.SortExpression)) { columnField.SortExpression = columnField.SortExpression + " DESC"; } } columnField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? selectComponent.ColumnHeaderText : reportField.ColumnHeaderText; if (!string.IsNullOrEmpty(columnField.SortExpression)) { reportFieldSortExpressions.AddOrReplace(reportField.Guid, columnField.SortExpression); } columnField.Visible = reportField.ShowInGrid; gReport.Columns.Add(columnField); if (mergeField) { gReport.CommunicateMergeFields.Add($"Data_{fieldId}|{columnField.HeaderText.RemoveSpecialCharacters()}"); } if (recipientField) { string fieldName = (selectComponent is IRecipientDataSelect) ? $"Recipient_{fieldId}" : $"Data_{fieldId}"; gReport.CommunicationRecipientPersonIdFields.Add(fieldName); } } catch (Exception ex) { ExceptionLogService.LogException(ex, HttpContext.Current); errors.Add(string.Format("{0} - {1}", selectComponent, ex.Message)); } } } } // if no fields are specified, show the default fields (Previewable/All) for the EntityType var dataColumns = gReport.Columns.OfType <object>().Where(a => a.GetType() != typeof(SelectField)); if (dataColumns.Count() == 0) { // show either the Previewable Columns or all (if there are no previewable columns) bool showAllColumns = !entityFields.Any(a => a.FieldKind == FieldKind.Property && a.IsPreviewable); foreach (var entityField in entityFields.Where(a => a.FieldKind == FieldKind.Property)) { columnIndex++; selectedEntityFields.Add(columnIndex, entityField); BoundField boundField = entityField.GetBoundFieldType(); boundField.DataField = string.Format("Entity_{0}_{1}", entityField.Name, columnIndex); boundField.HeaderText = entityField.Name; boundField.SortExpression = boundField.DataField; boundField.Visible = showAllColumns || entityField.IsPreviewable; gReport.Columns.Add(boundField); } } try { gReport.Visible = true; gReport.ExportFilename = report.Name; SortProperty sortProperty = gReport.SortProperty; if (sortProperty == null) { var reportSort = new SortProperty(); var sortColumns = new Dictionary <string, SortDirection>(); foreach (var reportField in report.ReportFields.Where(a => a.SortOrder.HasValue).OrderBy(a => a.SortOrder.Value)) { if (reportFieldSortExpressions.ContainsKey(reportField.Guid)) { var sortField = reportFieldSortExpressions[reportField.Guid]; if (!string.IsNullOrWhiteSpace(sortField)) { sortColumns.Add(sortField, reportField.SortDirection); } } } if (sortColumns.Any()) { reportSort.Property = sortColumns.Select(a => a.Key + (a.Value == SortDirection.Descending ? " desc" : string.Empty)).ToList().AsDelimited(","); sortProperty = reportSort; } } var qryErrors = new List <string>(); System.Data.Entity.DbContext reportDbContext; dynamic qry = report.GetQueryable(entityType, selectedEntityFields, selectedAttributes, selectedComponents, sortProperty, dataViewFilterOverrides, databaseTimeoutSeconds ?? 180, isCommunication, out qryErrors, out reportDbContext); errors.AddRange(qryErrors); if (!string.IsNullOrEmpty(report.QueryHint) && reportDbContext is RockContext) { using (new QueryHintScope(reportDbContext as RockContext, report.QueryHint)) { gReport.SetLinqDataSource(qry); } } else { gReport.SetLinqDataSource(qry); } gReport.DataBind(); } catch (Exception ex) { Exception exception = ex; ExceptionLogService.LogException(ex, HttpContext.Current); while (exception != null) { if (exception is System.Data.SqlClient.SqlException) { // if there was a SQL Server Timeout, have the warning be a friendly message about that. if ((exception as System.Data.SqlClient.SqlException).Number == -2) { errorMessage = "This report did not complete in a timely manner. You can try again or adjust the timeout setting of this block."; return; } else { errors.Add(exception.Message); exception = exception.InnerException; } } else { errors.Add(exception.Message); exception = exception.InnerException; } } } if (errors.Any()) { errorMessage = "WARNING: There was a problem with one or more of the report's data components...<br/><br/> " + errors.AsDelimited("<br/>"); } } }
public static void AddMergeFields(Dictionary <string, object> mergeFields, Person targetPerson, DateRange dateRange, List <Guid> excludedCurrencyTypes, List <Guid> accountGuids = null) { RockContext rockContext = new RockContext(); FinancialTransactionDetailService financialTransactionDetailService = new FinancialTransactionDetailService(rockContext); // fetch all the possible PersonAliasIds that have this GivingID to help optimize the SQL var personAliasIds = new PersonAliasService(rockContext).Queryable().Where(a => a.Person.GivingId == targetPerson.GivingId).Select(a => a.Id).ToList(); // get the transactions for the person or all the members in the person's giving group (Family) var qry = financialTransactionDetailService.Queryable().AsNoTracking() .Where(t => t.Transaction.AuthorizedPersonAliasId.HasValue && personAliasIds.Contains(t.Transaction.AuthorizedPersonAliasId.Value)); qry = qry.Where(t => t.Transaction.TransactionDateTime.Value >= dateRange.Start && t.Transaction.TransactionDateTime.Value <= dateRange.End); if (accountGuids == null) { qry = qry.Where(t => t.Account.IsTaxDeductible); } else { qry = qry.Where(t => accountGuids.Contains(t.Account.Guid)); } var excludedQry = qry; if (excludedCurrencyTypes.Count > 0) { qry = qry.Where(t => !excludedCurrencyTypes.Contains(t.Transaction.FinancialPaymentDetail.CurrencyTypeValue.Guid)); excludedQry = excludedQry.Where(t => excludedCurrencyTypes.Contains(t.Transaction.FinancialPaymentDetail.CurrencyTypeValue.Guid)); excludedQry = excludedQry.OrderByDescending(t => t.Transaction.TransactionDateTime); } qry = qry.OrderByDescending(t => t.Transaction.TransactionDateTime); mergeFields.Add("StatementStartDate", dateRange.Start?.ToShortDateString()); mergeFields.Add("StatementEndDate", dateRange.End?.ToShortDateString()); var familyGroupTypeId = GroupTypeCache.Get(Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY).Id; var groupMemberQry = new GroupMemberService(rockContext).Queryable(true).Where(m => m.Group.GroupTypeId == familyGroupTypeId); int recordTypeValueIdBusiness = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_BUSINESS.AsGuid()).Id; // get giving group members in order by family role (adult -> child) and then gender (male -> female) var givingGroup = new PersonService(rockContext).Queryable(true).AsNoTracking() .Where(p => p.GivingId == targetPerson.GivingId) .GroupJoin( groupMemberQry, p => p.Id, m => m.PersonId, (p, m) => new { p, m }) .SelectMany(x => x.m.DefaultIfEmpty(), (y, z) => new { Person = y.p, GroupMember = z }) .Select(p => new { FirstName = p.Person.NickName, LastName = p.Person.LastName, FamilyRoleOrder = p.GroupMember.GroupRole.Order, Gender = p.Person.Gender, PersonId = p.Person.Id, IsBusiness = p.Person.RecordTypeValueId == recordTypeValueIdBusiness }) .DistinctBy(p => p.PersonId) .OrderBy(p => p.FamilyRoleOrder).ThenBy(p => p.Gender) .ToList(); string salutation = string.Empty; if (givingGroup.FirstOrDefault() != null && givingGroup.FirstOrDefault().IsBusiness) { //If it's a business use the last name salutation = givingGroup.FirstOrDefault().LastName; } else { if (givingGroup.GroupBy(g => g.LastName).Count() == 1) { salutation = string.Join(", ", givingGroup.Select(g => g.FirstName)) + " " + givingGroup.FirstOrDefault().LastName; if (salutation.Contains(",")) { salutation = salutation.ReplaceLastOccurrence(",", " &"); } } else { salutation = string.Join(", ", givingGroup.Select(g => g.FirstName + " " + g.LastName)); if (salutation.Contains(",")) { salutation = salutation.ReplaceLastOccurrence(",", " &"); } } } mergeFields.Add("Salutation", salutation); var mailingAddress = targetPerson.GetMailingLocation(); //Sometimes we have an address that isn't a mailing address but still need it //This is the fallback if there is no mailing address if (mailingAddress == null) { var homeAddressGuid = Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_HOME.AsGuidOrNull(); var workAddressGuid = Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_WORK.AsGuidOrNull(); if (homeAddressGuid.HasValue && workAddressGuid.HasValue) { var homeAddressDv = DefinedValueCache.Get(homeAddressGuid.Value); var workAddressDv = DefinedValueCache.Get(workAddressGuid.Value); var family = targetPerson.GetFamilies(); var mailingLocations = family.SelectMany(f => f.GroupLocations) .Where(l => l.GroupLocationTypeValueId == homeAddressDv.Id || l.GroupLocationTypeValueId == workAddressDv.Id) .OrderBy(l => l.IsMappedLocation ? 0 : 1) .ThenBy(l => l.GroupLocationTypeValueId == homeAddressDv.Id ? 0 : 1); mailingAddress = mailingLocations.Select(l => l.Location).FirstOrDefault(); } } if (mailingAddress != null) { mergeFields.Add("StreetAddress1", mailingAddress.Street1); mergeFields.Add("StreetAddress2", mailingAddress.Street2); mergeFields.Add("City", mailingAddress.City); mergeFields.Add("State", mailingAddress.State); mergeFields.Add("PostalCode", mailingAddress.PostalCode); mergeFields.Add("Country", mailingAddress.Country); } else { mergeFields.Add("StreetAddress1", string.Empty); mergeFields.Add("StreetAddress2", string.Empty); mergeFields.Add("City", string.Empty); mergeFields.Add("State", string.Empty); mergeFields.Add("PostalCode", string.Empty); mergeFields.Add("Country", string.Empty); } var transactionDetails = qry.GroupJoin(new AttributeValueService(rockContext).Queryable(), ft => ft.Id, av => av.Id, (obj, av) => new { Transaction = obj, AttributeValues = av }) .ToList() .Select(obj => { obj.Transaction.Attributes = obj.AttributeValues.Select(av2 => AttributeCache.Get(av2.Attribute)).ToDictionary(k => k.Key, v => v); obj.Transaction.AttributeValues = obj.AttributeValues.Select(av2 => new AttributeValueCache(av2)).ToDictionary(k => k.AttributeKey, v => v); return(obj.Transaction); }); mergeFields.Add("TransactionDetails", transactionDetails); if (excludedCurrencyTypes.Count > 0) { mergeFields.Add("ExcludedTransactionDetails", excludedQry.ToList()); } mergeFields.Add("AccountSummary", qry.GroupBy(t => new { t.Account.Name, t.Account.PublicName, t.Account.Description }) .Select(s => new AccountSummary { AccountName = s.Key.Name, PublicName = s.Key.PublicName, Description = s.Key.Description, Total = s.Sum(a => a.Amount), Order = s.Max(a => a.Account.Order) }) .OrderBy(s => s.Order)); // pledge information var pledges = new FinancialPledgeService(rockContext).Queryable().AsNoTracking() .Where(p => p.PersonAliasId.HasValue && personAliasIds.Contains(p.PersonAliasId.Value) && p.StartDate <= dateRange.End && p.EndDate >= dateRange.Start) .GroupBy(p => p.Account) .Select(g => new PledgeSummary { AccountId = g.Key.Id, AccountName = g.Key.Name, PublicName = g.Key.PublicName, AmountPledged = g.Sum(p => p.TotalAmount), PledgeStartDate = g.Min(p => p.StartDate), PledgeEndDate = g.Max(p => p.EndDate) }) .ToList(); // add detailed pledge information foreach (var pledge in pledges) { var adjustedPledgeEndDate = pledge.PledgeEndDate.Value.Date; if (adjustedPledgeEndDate != DateTime.MaxValue.Date) { adjustedPledgeEndDate = adjustedPledgeEndDate.AddDays(1); } if (adjustedPledgeEndDate > dateRange.End) { adjustedPledgeEndDate = dateRange.End.Value; } if (adjustedPledgeEndDate > RockDateTime.Now) { adjustedPledgeEndDate = RockDateTime.Now; } pledge.AmountGiven = new FinancialTransactionDetailService(rockContext).Queryable() .Where(t => t.AccountId == pledge.AccountId && t.Transaction.AuthorizedPersonAliasId.HasValue && personAliasIds.Contains(t.Transaction.AuthorizedPersonAliasId.Value) && t.Transaction.TransactionDateTime >= pledge.PledgeStartDate && t.Transaction.TransactionDateTime < adjustedPledgeEndDate) .Sum(t => ( decimal? )t.Amount) ?? 0; pledge.AmountRemaining = (pledge.AmountGiven > pledge.AmountPledged) ? 0 : (pledge.AmountPledged - pledge.AmountGiven); if (pledge.AmountPledged > 0) { var test = ( double )pledge.AmountGiven / ( double )pledge.AmountPledged; pledge.PercentComplete = ( int )((pledge.AmountGiven * 100) / pledge.AmountPledged); } } mergeFields.Add("Pledges", pledges); }
private void SaveTransaction(FinancialGateway financialGateway, GatewayComponent gateway, Person person, PaymentInfo paymentInfo, FinancialTransaction transaction, RockContext rockContext) { transaction.AuthorizedPersonAliasId = person.PrimaryAliasId; if (RockTransactionEntry != null) { RockCheckBox cbGiveAnonymouslyControl = (( RockCheckBox )(RockTransactionEntry.FindControl("cbGiveAnonymously"))); if (cbGiveAnonymouslyControl != null) { transaction.ShowAsAnonymous = cbGiveAnonymouslyControl.Checked; } } transaction.TransactionDateTime = RockDateTime.Now; transaction.FinancialGatewayId = financialGateway.Id; var txnType = DefinedValueCache.Get(this.GetAttributeValue("TransactionType").AsGuidOrNull() ?? Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()); transaction.TransactionTypeValueId = txnType.Id; transaction.Summary = paymentInfo.Comment1; if (transaction.FinancialPaymentDetail == null) { transaction.FinancialPaymentDetail = new FinancialPaymentDetail(); } transaction.FinancialPaymentDetail.SetFromPaymentInfo(paymentInfo, gateway, rockContext); Guid sourceGuid = Guid.Empty; if (Guid.TryParse(GetAttributeValue("Source"), out sourceGuid)) { var source = DefinedValueCache.Get(sourceGuid); if (source != null) { transaction.SourceTypeValueId = source.Id; } } var transactionEntity = this.GetTransactionEntity(); foreach (var account in GetSelectedAccounts().Where(a => a.Amount > 0)) { var transactionDetail = new FinancialTransactionDetail(); transactionDetail.Amount = account.Amount; transactionDetail.AccountId = account.Id; if (transactionEntity != null) { transactionDetail.EntityTypeId = transactionEntity.TypeId; transactionDetail.EntityId = transactionEntity.Id; } transaction.TransactionDetails.Add(transactionDetail); } var batchService = new FinancialBatchService(rockContext); // Get the batch var batch = batchService.Get( GetAttributeValue("BatchNamePrefix"), paymentInfo.CurrencyTypeValue, paymentInfo.CreditCardTypeValue, transaction.TransactionDateTime.Value, financialGateway.GetBatchTimeOffset()); var batchChanges = new History.HistoryChangeList(); if (batch.Id == 0) { batchChanges.AddCustom("Add", "Record", "Generated the batch"); History.EvaluateChange(batchChanges, "Batch Name", string.Empty, batch.Name); History.EvaluateChange(batchChanges, "Status", null, batch.Status); History.EvaluateChange(batchChanges, "Start Date/Time", null, batch.BatchStartDateTime); History.EvaluateChange(batchChanges, "End Date/Time", null, batch.BatchEndDateTime); } decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount; History.EvaluateChange(batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency()); batch.ControlAmount = newControlAmount; transaction.BatchId = batch.Id; transaction.LoadAttributes(rockContext); var allowedTransactionAttributes = GetAttributeValue("AllowedTransactionAttributesFromURL").Split(',').AsGuidList().Select(x => AttributeCache.Get(x).Key); foreach (KeyValuePair <string, AttributeValueCache> attr in transaction.AttributeValues) { if (PageParameters().ContainsKey("Attribute_" + attr.Key) && allowedTransactionAttributes.Contains(attr.Key)) { attr.Value.Value = Server.UrlDecode(PageParameter("Attribute_" + attr.Key)); } } batch.Transactions.Add(transaction); rockContext.SaveChanges(); transaction.SaveAttributeValues(); HistoryService.SaveChanges( rockContext, typeof(FinancialBatch), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), batch.Id, batchChanges ); SendReceipt(transaction.Id); TransactionCode = transaction.TransactionCode; }
/// <summary> /// Gets either a delimited string of email addresses or a list of recipients from an attribute value. /// </summary> /// <param name="recipientType">The recipient type.</param> /// <param name="attributeValue">The attribute value.</param> /// <param name="action">The action.</param> /// <param name="mergeFields">The merge fields.</param> /// <param name="rockContext">The rock context.</param> /// <param name="delimitedEmails">The delimited emails.</param> /// <param name="recipientList">The recipient list.</param> /// <returns></returns> private bool GetEmailsFromAttributeValue(RecipientType recipientType, string attributeValue, WorkflowAction action, Dictionary <string, object> mergeFields, RockContext rockContext, out string delimitedEmails, out List <RockEmailMessageRecipient> recipientList) { delimitedEmails = null; recipientList = null; Guid?guid = attributeValue.AsGuidOrNull(); if (guid.HasValue) { var attribute = AttributeCache.Get(guid.Value, rockContext); if (attribute != null) { var recipientTypePrefix = string.Empty; var groupRoleAttributeKey = AttributeKey.GroupRole; switch (recipientType) { case RecipientType.CC: recipientTypePrefix = "CC "; break; case RecipientType.BCC: recipientTypePrefix = "BCC "; break; } string toValue = action.GetWorkflowAttributeValue(guid.Value); if (!string.IsNullOrWhiteSpace(toValue)) { switch (attribute.FieldType.Class) { case "Rock.Field.Types.TextFieldType": case "Rock.Field.Types.EmailFieldType": { delimitedEmails = toValue; return(true); } case "Rock.Field.Types.PersonFieldType": { Guid personAliasGuid = toValue.AsGuid(); if (!personAliasGuid.IsEmpty()) { var person = new PersonAliasService(rockContext).Queryable() .Where(a => a.Guid.Equals(personAliasGuid)) .Select(a => a.Person) .FirstOrDefault(); if (person == null) { action.AddLogEntry($"Invalid {recipientTypePrefix}Recipient: Person not found", true); } else if (string.IsNullOrWhiteSpace(person.Email)) { action.AddLogEntry($"{recipientTypePrefix}Email was not sent: Recipient does not have an email address", true); } else if (!person.IsEmailActive) { action.AddLogEntry($"{recipientTypePrefix}Email was not sent: Recipient email is not active", true); } else if (person.EmailPreference == EmailPreference.DoNotEmail) { action.AddLogEntry($"{recipientTypePrefix}Email was not sent: Recipient has requested 'Do Not Email'", true); } else { var personDict = new Dictionary <string, object>(mergeFields) { { "Person", person } }; recipientList = new List <RockEmailMessageRecipient> { new RockEmailMessageRecipient(person, personDict) }; return(true); } } return(false); } case "Rock.Field.Types.GroupFieldType": case "Rock.Field.Types.SecurityRoleFieldType": { int? groupId = toValue.AsIntegerOrNull(); Guid?groupGuid = toValue.AsGuidOrNull(); /* * 2020-03-25 - JPH * * Per Jon, even though the user may select a Group or Security Role Attribute for the CC and BCC * Attributes, we only want to allow Group Role filtering for the 'Send To Email Addresses' Attribute. * Otherwise, the UI starts to become too overwhelming for the end user making the selections. */ Guid?groupRoleValueGuid = recipientType == RecipientType.SendTo ? GetGroupRoleValueGuid(action, groupRoleAttributeKey) : null; IQueryable <GroupMember> qry = null; // Handle situations where the attribute value is the ID if (groupId.HasValue) { qry = new GroupMemberService(rockContext).GetByGroupId(groupId.Value); } else if (groupGuid.HasValue) { // Handle situations where the attribute value stored is the Guid qry = new GroupMemberService(rockContext).GetByGroupGuid(groupGuid.Value); } else { action.AddLogEntry($"Invalid {recipientTypePrefix}Recipient: No valid group id or Guid", true); } if (groupRoleValueGuid.HasValue) { qry = qry.Where(m => m.GroupRole != null && m.GroupRole.Guid.Equals(groupRoleValueGuid.Value)); } if (qry != null) { recipientList = new List <RockEmailMessageRecipient>(); foreach (var person in qry .Where(m => m.GroupMemberStatus == GroupMemberStatus.Active) .Select(m => m.Person)) { if (person.IsEmailActive && person.EmailPreference != EmailPreference.DoNotEmail && !string.IsNullOrWhiteSpace(person.Email)) { var personDict = new Dictionary <string, object>(mergeFields) { { "Person", person } }; recipientList.Add(new RockEmailMessageRecipient(person, personDict)); } } return(true); } return(false); } } } } } else if (!string.IsNullOrWhiteSpace(attributeValue)) { delimitedEmails = attributeValue; return(true); } return(false); }
private void CreateControls(bool setValues) { fsAttributes.Controls.Clear(); string validationGroup = string.Format("vgAttributeValues_{0}", this.BlockId); valSummaryTop.ValidationGroup = validationGroup; btnSave.ValidationGroup = validationGroup; hfAttributeOrder.Value = AttributeList.AsDelimited("|"); if (Person != null) { foreach (int attributeId in AttributeList) { var attribute = AttributeCache.Get(attributeId); string attributeValue = Person.GetAttributeValue(attribute.Key); string formattedValue = string.Empty; if (ViewMode != VIEW_MODE_EDIT || !attribute.IsAuthorized(Authorization.EDIT, CurrentPerson)) { if (ViewMode == VIEW_MODE_ORDER && _canAdministrate) { var div = new HtmlGenericControl("div"); fsAttributes.Controls.Add(div); div.Attributes.Add("data-attribute-id", attribute.Id.ToString()); div.Attributes.Add("class", "form-group"); var a = new HtmlGenericControl("a"); div.Controls.Add(a); var i = new HtmlGenericControl("i"); a.Controls.Add(i); i.Attributes.Add("class", "fa fa-bars"); div.Controls.Add(new LiteralControl(" " + attribute.Name)); } else { if (attribute.FieldType.Class == typeof(Rock.Field.Types.ImageFieldType).FullName) { formattedValue = attribute.FieldType.Field.FormatValueAsHtml(fsAttributes, attribute.EntityTypeId, Person.Id, attributeValue, attribute.QualifierValues, true); } else { formattedValue = attribute.FieldType.Field.FormatValueAsHtml(fsAttributes, attribute.EntityTypeId, Person.Id, attributeValue, attribute.QualifierValues, false); } if (!string.IsNullOrWhiteSpace(formattedValue)) { if (attribute.FieldType.Class == typeof(Rock.Field.Types.MatrixFieldType).FullName) { fsAttributes.Controls.Add(new RockLiteral { Label = attribute.Name, Text = formattedValue, CssClass = "matrix-attribute" }); } else { fsAttributes.Controls.Add(new RockLiteral { Label = attribute.Name, Text = formattedValue }); } } } } else { attribute.AddControl(fsAttributes.Controls, attributeValue, validationGroup, setValues, true); } } } pnlActions.Visible = (ViewMode != VIEW_MODE_VIEW); }
/// <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); string to = GetAttributeValue(action, AttributeKey.To); string fromValue = GetAttributeValue(action, AttributeKey.From); string subject = GetAttributeValue(action, AttributeKey.Subject); string body = GetAttributeValue(action, AttributeKey.Body); string cc = GetActionAttributeValue(action, AttributeKey.Cc); string bcc = GetActionAttributeValue(action, AttributeKey.Bcc); var attachmentOneGuid = GetAttributeValue(action, AttributeKey.AttachmentOne, true).AsGuid(); var attachmentTwoGuid = GetAttributeValue(action, AttributeKey.AttachmentTwo, true).AsGuid(); var attachmentThreeGuid = GetAttributeValue(action, AttributeKey.AttachmentThree, true).AsGuid(); var attachmentList = new List <BinaryFile>(); if (!attachmentOneGuid.IsEmpty()) { attachmentList.Add(new BinaryFileService(rockContext).Get(attachmentOneGuid)); } if (!attachmentTwoGuid.IsEmpty()) { attachmentList.Add(new BinaryFileService(rockContext).Get(attachmentTwoGuid)); } if (!attachmentThreeGuid.IsEmpty()) { attachmentList.Add(new BinaryFileService(rockContext).Get(attachmentThreeGuid)); } var attachments = attachmentList.ToArray(); bool createCommunicationRecord = GetAttributeValue(action, AttributeKey.SaveCommunicationHistory).AsBoolean(); string fromEmailAddress = string.Empty; string fromName = string.Empty; Guid? fromGuid = fromValue.AsGuidOrNull(); if (fromGuid.HasValue) { var attribute = AttributeCache.Get(fromGuid.Value, rockContext); if (attribute != null) { string fromAttributeValue = action.GetWorkflowAttributeValue(fromGuid.Value); if (!string.IsNullOrWhiteSpace(fromAttributeValue)) { if (attribute.FieldType.Class == "Rock.Field.Types.PersonFieldType") { Guid personAliasGuid = fromAttributeValue.AsGuid(); if (!personAliasGuid.IsEmpty()) { var person = new PersonAliasService(rockContext).Queryable() .Where(a => a.Guid.Equals(personAliasGuid)) .Select(a => a.Person) .FirstOrDefault(); if (person != null && !string.IsNullOrWhiteSpace(person.Email)) { fromEmailAddress = person.Email; fromName = person.FullName; } } } else { fromEmailAddress = fromAttributeValue; } } } } else { fromEmailAddress = fromValue.ResolveMergeFields(mergeFields); } // to if (GetEmailsFromAttributeValue(RecipientType.SendTo, to, action, mergeFields, rockContext, out string toDelimitedEmails, out List <RockEmailMessageRecipient> toRecipients)) { // cc GetEmailsFromAttributeValue(RecipientType.CC, cc, action, mergeFields, rockContext, out string ccDelimitedEmails, out List <RockEmailMessageRecipient> ccRecipients); List <string> ccEmails = BuildEmailList(ccDelimitedEmails, mergeFields, ccRecipients); // bcc GetEmailsFromAttributeValue(RecipientType.BCC, bcc, action, mergeFields, rockContext, out string bccDelimitedEmails, out List <RockEmailMessageRecipient> bccRecipients); List <string> bccEmails = BuildEmailList(bccDelimitedEmails, mergeFields, bccRecipients); if (!string.IsNullOrWhiteSpace(toDelimitedEmails)) { Send(toDelimitedEmails, fromEmailAddress, fromName, subject, body, ccEmails, bccEmails, mergeFields, createCommunicationRecord, attachments, out errorMessages); } else if (toRecipients != null) { Send(toRecipients, fromEmailAddress, fromName, subject, body, ccEmails, bccEmails, createCommunicationRecord, attachments, out errorMessages); } } errorMessages.ForEach(m => action.AddLogEntry(m, true)); return(true); }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The workflow action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public override bool Execute(RockContext rockContext, Model.WorkflowAction action, Object entity, out List <string> errorMessages) { var checkInState = GetCheckInState(entity, out errorMessages); if (checkInState == null) { return(false); } var family = checkInState.CheckIn.CurrentFamily; if (family != null) { var remove = GetAttributeValue(action, "Remove").AsBoolean(); bool removeSNGroups = GetAttributeValue(action, "RemoveSpecialNeedsGroups").AsBoolean(true); bool removeNonSNGroups = GetAttributeValue(action, "RemoveNonSpecialNeedsGroups").AsBoolean(); // get the admin-selected attribute key instead of using a hardcoded key var personSpecialNeedsKey = string.Empty; var personSpecialNeedsGuid = GetAttributeValue(action, "PersonSpecialNeedsAttribute").AsGuid(); if (personSpecialNeedsGuid != Guid.Empty) { personSpecialNeedsKey = AttributeCache.Get(personSpecialNeedsGuid, rockContext).Key; } var groupSpecialNeedsKey = string.Empty; var groupSpecialNeedsGuid = GetAttributeValue(action, "GroupSpecialNeedsAttribute").AsGuid(); if (groupSpecialNeedsGuid != Guid.Empty) { groupSpecialNeedsKey = AttributeCache.Get(groupSpecialNeedsGuid, rockContext).Key; } // log a warning if the attribute is missing or invalid if (string.IsNullOrWhiteSpace(personSpecialNeedsKey)) { action.AddLogEntry(string.Format("The Person Special Needs attribute is not selected or invalid for '{0}'.", action.ActionTypeCache.Name)); } if (string.IsNullOrWhiteSpace(groupSpecialNeedsKey)) { action.AddLogEntry(string.Format("The Group Special Needs attribute is not selected or invalid for '{0}'.", action.ActionTypeCache.Name)); } foreach (var person in family.People) { if (person.Person.Attributes == null) { person.Person.LoadAttributes(rockContext); } bool isSNPerson = person.Person.GetAttributeValue(personSpecialNeedsKey).AsBoolean(); foreach (var groupType in person.GroupTypes.ToList()) { foreach (var group in groupType.Groups.ToList()) { bool isSNGroup = group.Group.GetAttributeValue(groupSpecialNeedsKey).AsBoolean(); // If the group is special needs but the person is not, then remove it. if (removeSNGroups && isSNGroup && !(isSNPerson)) { if (remove) { groupType.Groups.Remove(group); } else { group.ExcludedByFilter = true; } continue; } // or if the setting is enabled and the person is SN but the group is not. if (removeNonSNGroups && isSNPerson && !isSNGroup) { if (remove) { groupType.Groups.Remove(group); } else { group.ExcludedByFilter = true; } } } } } } return(true); }
public async Task ExecuteAsync(IJobExecutionContext context) { // Get the configuration for the job JobDataMap dataMap = context.JobDetail.JobDataMap; var approvalAttributeGuid = dataMap.GetString(AttributeKey_ApprovedAttribute).AsGuid(); var approvalAttribute = AttributeCache.Get(approvalAttributeGuid); // Collect some values for matching var campuses = CampusCache.All(); var audiences = DefinedTypeCache.Get(Rock.SystemGuid.DefinedType.MARKETING_CAMPAIGN_AUDIENCE_TYPE).DefinedValues; // Get the calendars var calendarGuid = dataMap.GetString(AttributeKey_Calendar).AsGuid(); var publicCalendarGuid = dataMap.GetString(AttributeKey_PublicCalendar).AsGuidOrNull(); var calendar = EventCalendarCache.Get(calendarGuid); var publicCalendar = publicCalendarGuid.HasValue ? EventCalendarCache.Get(publicCalendarGuid.Value) : null; // Get the login credentials string eSpaceUsername = dataMap.GetString(AttributeKey_eSpaceUsername); string eSpacePassword = dataMap.GetString(AttributeKey_eSpacePassword); // Decrypt the password eSpacePassword = Rock.Security.Encryption.DecryptString(eSpacePassword); // Create a new api client var client = new Client(); // Log in client.SetCredentials(eSpaceUsername, eSpacePassword); // Get all future events var eSpaceEvents = await client.GetEvents(new GetEventsOptions { StartDate = DateTime.Now, TopX = 2000 }); // Group by event id (the eSpace api returns "events" as a merged event and schedule) var eSpaceEventsById = eSpaceEvents.GroupBy(e => e.EventId); var eventTotalCount = eSpaceEventsById.Count(); // Loop through each eSpace event group var eventSyncedCount = 0; var eventErrorCount = 0; foreach (var eSpaceEventGroup in eSpaceEventsById) { eventSyncedCount++; try { // Use the first item as the main event - Note that some properties // here are actually part of the schedule, not the event var eSpaceEvent = eSpaceEventGroup.FirstOrDefault(); // Skip draft events if (eSpaceEvent.Status == "Draft") { continue; } // Update the job status context.UpdateLastStatusMessage($@"Syncing event {eventSyncedCount} of {eventTotalCount} ({Math.Round( (double) eventSyncedCount / eventTotalCount * 100, 0 )}%, {eventErrorCount} events with errors)"); // Sync the event await SyncHelper.SyncEvent( client, eSpaceEvent, new GetEventOccurrencesOptions { StartDate = DateTime.Now }, calendar, publicCalendar, null, approvalAttribute?.Key ); } catch (Exception ex) { ExceptionLogService.LogException(ex, null); eventErrorCount++; } } var eSpaceEventIds = eSpaceEvents.Select(e => e.EventId).ToArray(); var rockContext = new RockContext(); var eventItemService = new EventItemService(rockContext); var desyncedEvents = eventItemService.Queryable().Where(e => e.ForeignKey == SyncHelper.ForeignKey_eSpaceEventId && !eSpaceEventIds.Contains(e.ForeignId)); if (desyncedEvents.Any()) { eventItemService.DeleteRange(desyncedEvents); rockContext.SaveChanges(); } // Update the job status context.UpdateLastStatusMessage($@"Synced {eventSyncedCount} events with {eventErrorCount} errors."); }
/// <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>(); Guid? groupGuid = null; string filterValue = string.Empty; string filterKey = string.Empty; // get the group attribute groupGuid = GetAttributeValue(action, "SelectionGroup").AsGuid(); if (!groupGuid.HasValue) { errorMessages.Add("The selection group could not be found!"); } // get filter key filterKey = GetAttributeValue(action, "GroupMemberAttributeKey"); // get the filter value filterValue = GetAttributeValue(action, "FilterValue"); Guid?filterValueGuid = filterValue.AsGuidOrNull(); if (filterValueGuid.HasValue) { filterValue = action.GetWorkflowAttributeValue(filterValueGuid.Value); } else { filterValue = filterValue.ResolveMergeFields(GetMergeFields(action)); } // get group members var qry = new GroupMemberService(rockContext).Queryable().AsNoTracking() .Where(g => g.Group.Guid == groupGuid); if (!string.IsNullOrWhiteSpace(filterKey)) { qry = qry.WhereAttributeValue(rockContext, filterKey, filterValue); } var groupMembers = qry.Select(g => new { g.Person.NickName, g.Person.LastName, g.Person.SuffixValueId, PrimaryAliasGuid = g.Person.Aliases.FirstOrDefault().Guid }) .ToList(); if (groupMembers.Count() > 0) { // get random group member from options Random rnd = new Random(); int r = rnd.Next(groupMembers.Count); var selectedGroupMember = groupMembers[r]; // set value Guid selectPersonGuid = GetAttributeValue(action, "SelectedPerson").AsGuid(); if (!selectPersonGuid.IsEmpty()) { var selectedPersonAttribute = AttributeCache.Get(selectPersonGuid, rockContext); if (selectedPersonAttribute != null) { // If this is a person type attribute if (selectedPersonAttribute.FieldTypeId == FieldTypeCache.Get(Rock.SystemGuid.FieldType.PERSON.AsGuid(), rockContext).Id) { SetWorkflowAttributeValue(action, selectPersonGuid, selectedGroupMember.PrimaryAliasGuid.ToString()); } else if (selectedPersonAttribute.FieldTypeId == FieldTypeCache.Get(Rock.SystemGuid.FieldType.TEXT.AsGuid(), rockContext).Id) { SetWorkflowAttributeValue(action, selectPersonGuid, Person.FormatFullName(selectedGroupMember.NickName, selectedGroupMember.LastName, selectedGroupMember.SuffixValueId)); } } } } else { errorMessages.Add("No group member for the selected campus could be found."); } errorMessages.ForEach(m => action.AddLogEntry(m, true)); return(true); }
public static IEnumerable <Person> GetByMatch(this PersonService personService, String firstName, String lastName, DateTime?birthDate, String email = null, String phone = null, String street1 = null, String postalCode = null, bool createNameless = false) { using (Rock.Data.RockContext context = new Rock.Data.RockContext()) { //FirstName LastName and (DOB or email or phone or street address) are required. If not return an empty list. if (firstName.IsNullOrWhiteSpace() || lastName.IsNullOrWhiteSpace() || (!birthDate.HasValue && email.IsNullOrWhiteSpace() && phone.IsNullOrWhiteSpace() && street1.IsNullOrWhiteSpace())) { if (createNameless && (email.IsNotNullOrWhiteSpace() || phone.IsNotNullOrWhiteSpace())) { return(new List <Person> { GetOrCreateNamelessPerson(email, phone, personService) }); } else { return(new List <Person>()); } } LocationService locationService = new LocationService(context); AttributeValueService attributeValueService = new AttributeValueService(context); List <AttributeValue> attributeValues = attributeValueService.GetByAttributeId(AttributeCache.Get(GOES_BY_ATTRIBUTE.AsGuid()).Id).ToList(); var diminutiveName = DefinedTypeCache.Get(DIMINUTIVE_NAMES.AsGuid()); firstName = firstName ?? string.Empty; lastName = lastName ?? string.Empty; email = email.ToLower() ?? string.Empty; phone = PhoneNumber.CleanNumber(phone ?? string.Empty); List <Person> matchingPersons = new List <Person>(); // Do a quick check to see if we get a match right up front List <Person> persons = new List <Person>(); if (birthDate.HasValue || !string.IsNullOrEmpty(email)) { var fastQuery = personService.Queryable(false, false).Where(p => (p.FirstName.ToLower() == firstName.ToLower() || p.NickName.ToLower() == firstName.ToLower()) && p.LastName == lastName); if (birthDate.HasValue) { fastQuery = fastQuery.Where(p => p.BirthDate == birthDate); } if (!String.IsNullOrEmpty(email)) { fastQuery = fastQuery.Where(p => p.Email.ToLower() == email); } persons = fastQuery.ToList(); // We have an exact match. Just be done. if (persons.Count == 1) { return(persons); } } // Go ahead and do this more leniant search if we get this far persons = personService.Queryable(false, false) .Where(p => p.LastName == lastName && (!birthDate.HasValue || p.BirthDate == null || (birthDate.HasValue && p.BirthDate.Value == birthDate.Value))) .ToList(); // Set a placeholder for the location so we only geocode it 1 time Location location = null; foreach (Person person in persons) { // Check to see if the phone exists anywhere in the family Boolean phoneExists = !string.IsNullOrWhiteSpace(phone) && person.GetFamilies().Where(f => f.Members.Where(m => m.Person.PhoneNumbers.Where(pn => pn.Number == phone).Any()).Any()).Any(); // Check to see if the email exists anywhere in the family Boolean emailExists = !string.IsNullOrWhiteSpace(email) && person.GetFamilies().Where(f => f.Members.Where(m => m.Person.Email == email).Any()).Any(); Boolean addressMatches = false; // Check the address if it was passed if (!string.IsNullOrEmpty(street1) && !string.IsNullOrEmpty(postalCode)) { if (person.GetHomeLocation() != null) { if (person.GetHomeLocation().Street1 == street1) { addressMatches = true; } // If it doesn't match, we need to geocode it and check it again if (location == null && !string.IsNullOrEmpty(street1) && !string.IsNullOrEmpty(postalCode)) { location = new Location(); location.Street1 = street1; location.PostalCode = postalCode; locationService.Verify(location, true); } if (location != null && !addressMatches && person.GetHomeLocation().Street1 == location.Street1) { addressMatches = true; } } } // At least phone, email, or address have to match if (phoneExists || emailExists || addressMatches) { matchingPersons.Add(person); } } List <Person> firstNameMatchingPersons = new List <Person>(); // Now narrow down the list by looking for the first name (or diminutive name) foreach (Person matchingPerson in matchingPersons) { if (firstName != null && ((matchingPerson.FirstName != null && matchingPerson.FirstName.ToLower() != firstName.ToLower()) || (matchingPerson.NickName != null && matchingPerson.NickName.ToLower() != firstName.ToLower()))) { foreach (DefinedValueCache dv in diminutiveName.DefinedValues) { AttributeValue av = attributeValues.Where(av2 => av2.EntityId == dv.Id).FirstOrDefault(); List <string> nameList = new List <string>(); nameList = av.Value.Split('|').ToList(); nameList.Add(dv.Value); if (nameList.Contains(firstName.ToLower()) && (nameList.Contains(matchingPerson.FirstName.ToLower()) || nameList.Contains(matchingPerson.NickName.ToLower()))) { firstNameMatchingPersons.Add(matchingPerson); break; } } } else { firstNameMatchingPersons.Add(matchingPerson); } } return(firstNameMatchingPersons); } }
/// <summary> /// Add all of the columns to the Registrations grid after the Registrants column. /// The Column.Insert method does not play well with buttons. /// </summary> private void RegistrationsTabAddDynamicControls() { var registrantsField = gRegistrations.ColumnsOfType <RockTemplateField>().FirstOrDefault(a => a.HeaderText == "Registrants"); int registrantsFieldIndex = gRegistrations.Columns.IndexOf(registrantsField); // Remove all columns to the right of Registrants for (int i = registrantsFieldIndex + 2; i < gRegistrations.Columns.Count; i++) { gRegistrations.Columns.RemoveAt(i); } // Add Attribute columns if necessary if (AvailableRegistrationAttributeIdsForGrid != null) { foreach (var attributeCache in AvailableRegistrationAttributeIdsForGrid.Select(a => AttributeCache.Get(a))) { bool columnExists = gRegistrations.Columns.OfType <AttributeField>().FirstOrDefault(a => a.AttributeId == attributeCache.Id) != null; if (!columnExists) { AttributeField boundField = new AttributeField(); boundField.DataField = attributeCache.Key; boundField.AttributeId = attributeCache.Id; boundField.HeaderText = attributeCache.Name; boundField.ItemStyle.HorizontalAlign = attributeCache.FieldType.Field.AlignValue; gRegistrations.Columns.Add(boundField); } } } // Add the rest of the columns var dtWhen = new DateTimeField { DataField = "CreatedDateTime", HeaderText = "When", SortExpression = "CreatedDateTime" }; dtWhen.HeaderStyle.HorizontalAlign = HorizontalAlign.Left; dtWhen.ItemStyle.HorizontalAlign = HorizontalAlign.Left; gRegistrations.Columns.Add(dtWhen); var lDiscount = new RockLiteralField { ID = "lDiscount", HeaderText = "Discount Code", SortExpression = "DiscountCode", Visible = false }; lDiscount.HeaderStyle.HorizontalAlign = HorizontalAlign.Left; lDiscount.ItemStyle.HorizontalAlign = HorizontalAlign.Left; gRegistrations.Columns.Add(lDiscount); var lRegistrationCost = new RockLiteralField { ID = "lRegistrationCost", HeaderText = "Total Cost", SortExpression = "TotalCost" }; lRegistrationCost.HeaderStyle.HorizontalAlign = HorizontalAlign.Right; lRegistrationCost.ItemStyle.HorizontalAlign = HorizontalAlign.Right; gRegistrations.Columns.Add(lRegistrationCost); var lBalance = new RockLiteralField { ID = "lBalance", HeaderText = "Balance Due", SortExpression = "BalanceDue" }; lBalance.HeaderStyle.HorizontalAlign = HorizontalAlign.Right; lBalance.ItemStyle.HorizontalAlign = HorizontalAlign.Right; gRegistrations.Columns.Add(lBalance); DeleteField deleteField = new DeleteField(); deleteField.Click += gRegistrations_Delete; gRegistrations.Columns.Add(deleteField); }
/// <summary> /// Gets the cache object associated with this Entity /// </summary> /// <returns></returns> public IEntityCache GetCacheObject() { return(AttributeCache.Get(this.Id)); }
/// <summary> /// Creates the dynamic person controls. /// </summary> /// <param name="person">The person.</param> /// <param name="setValues">if set to <c>true</c> [set values].</param> private void CreateDynamicPersonControls(FamilyRegistrationState.FamilyPersonState familyPersonState) { var fakePerson = new Person(); var attributeList = familyPersonState.PersonAttributeValuesState.Select(a => AttributeCache.Get(a.Value.AttributeId)).ToList(); fakePerson.Attributes = attributeList.ToDictionary(a => a.Key, v => v); fakePerson.AttributeValues = familyPersonState.PersonAttributeValuesState; var adultAttributeKeysToEdit = this.RequiredAttributesForAdults.OrderBy(a => a.Order).ToList(); adultAttributeKeysToEdit.AddRange(this.OptionalAttributesForAdults.OrderBy(a => a.Order).ToList()); avcAdultAttributes.IncludedAttributes = adultAttributeKeysToEdit.ToArray(); avcAdultAttributes.ValidationGroup = btnDonePerson.ValidationGroup; avcAdultAttributes.NumberOfColumns = 2; avcAdultAttributes.ShowCategoryLabel = false; avcAdultAttributes.AddEditControls(fakePerson); var childAttributeKeysToEdit = this.RequiredAttributesForChildren.OrderBy(a => a.Order).ToList(); childAttributeKeysToEdit.AddRange(this.OptionalAttributesForChildren.OrderBy(a => a.Order).ToList()); avcChildAttributes.IncludedAttributes = childAttributeKeysToEdit.ToArray(); avcChildAttributes.ValidationGroup = btnDonePerson.ValidationGroup; avcChildAttributes.NumberOfColumns = 2; avcChildAttributes.ShowCategoryLabel = false; avcChildAttributes.AddEditControls(fakePerson); // override the attribute's IsRequired and set Required based on whether the attribute is part of the Required or Optional set of attributes for the Registration foreach (Control attributeControl in avcAdultAttributes.ControlsOfTypeRecursive <Control>().OfType <Control>()) { if (attributeControl is IHasRequired && attributeControl.ID.IsNotNullOrWhiteSpace()) { int?attributeControlAttributeId = attributeControl.ID.Replace("attribute_field_", string.Empty).AsIntegerOrNull(); if (attributeControlAttributeId.HasValue) { (attributeControl as IHasRequired).Required = this.RequiredAttributesForAdults.Any(a => a.Id == attributeControlAttributeId.Value); } } } foreach (Control attributeControl in avcChildAttributes.ControlsOfTypeRecursive <Control>().OfType <Control>()) { if (attributeControl is IHasRequired && attributeControl.ID.IsNotNullOrWhiteSpace()) { int?attributeControlAttributeId = attributeControl.ID.Replace("attribute_field_", string.Empty).AsIntegerOrNull(); if (attributeControlAttributeId.HasValue) { (attributeControl as IHasRequired).Required = this.RequiredAttributesForChildren.Any(a => a.Id == attributeControlAttributeId.Value); } } } }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The workflow action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public override bool Execute(RockContext rockContext, Rock.Model.WorkflowAction action, Object entity, out List <string> errorMessages) { var checkInState = GetCheckInState(entity, out errorMessages); if (checkInState == null) { return(false); } var dataViewAttributeKey = string.Empty; var dataViewAttributeGuid = GetAttributeValue(action, "DataViewGroupAttribute").AsGuid(); if (dataViewAttributeGuid != Guid.Empty) { dataViewAttributeKey = AttributeCache.Get(dataViewAttributeGuid).Key; } var dataViewService = new DataViewService(new RockContext()); var family = checkInState.CheckIn.CurrentFamily; if (family != null) { var remove = GetAttributeValue(action, "Remove").AsBoolean(); foreach (var person in family.People) { foreach (var groupType in person.GroupTypes.ToList()) { foreach (var group in groupType.Groups.ToList()) { if (group.ExcludedByFilter == true) { continue; } var approvedPeopleGuid = group.Group.GetAttributeValue(dataViewAttributeKey); if (string.IsNullOrWhiteSpace(approvedPeopleGuid)) { continue; } //Get approved people dataview from cache or from db var approvedPeopleList = RockCache.Get(approvedPeopleGuid) as List <int>; if (approvedPeopleList == null) { DataView approvedPeople = dataViewService.Get(approvedPeopleGuid.AsGuid()); if (approvedPeople == null) { continue; } var errors = new List <string>(); var dbContext = approvedPeople.GetDbContext(); var approvedPeopleQry = (IQueryable <Person>)approvedPeople.GetQuery(null, dbContext, 30, out errors).AsNoTracking(); if (approvedPeopleQry != null) { try { approvedPeopleQry = approvedPeopleQry.Skip(0).Take(5000); approvedPeopleList = approvedPeopleQry.Select(e => e.Id).ToList(); RockCache.AddOrUpdate(approvedPeopleGuid, null, approvedPeopleList, RockDateTime.Now.AddMinutes(10), Constants.CACHE_TAG); } catch (Exception ex) { if (remove) { groupType.Groups.Remove(group); } else { group.ExcludedByFilter = true; } ExceptionLogService.LogException(ex); } } } if (approvedPeopleList != null && !approvedPeopleList.Contains(person.Person.Id)) { if (remove) { groupType.Groups.Remove(group); } else { group.ExcludedByFilter = true; } } } } } } return(true); }
/// <summary> /// Gets the name of the Twitter user. /// </summary> /// <param name="twitterUser">The Twitter user.</param> /// <param name="accessToken">The access token.</param> /// <returns></returns> public static string GetTwitterUser(dynamic twitterUser, string accessToken = "") { // accessToken is required if (accessToken.IsNullOrWhiteSpace()) { return(null); } string username = string.Empty; string twitterId = twitterUser.id_str; string twitterLink = "https://twitter.com/" + twitterUser.screen_name; string userName = "******" + twitterId; UserLogin user = null; using (var rockContext = new RockContext()) { // Query for an existing user var userLoginService = new UserLoginService(rockContext); user = userLoginService.GetByUserName(userName); // If no user was found, see if we can find a match in the person table if (user == null) { // Get name and email from twitterUser object and then split the name string fullName = twitterUser.name; string firstName = null; string lastName = null; var personService = new PersonService(rockContext); personService.SplitName(fullName, out firstName, out lastName); string email = string.Empty; try { email = twitterUser.email; } catch { } Person person = null; // If person had an email, get the first person with the same name and email address. if (!string.IsNullOrWhiteSpace(email)) { person = personService.FindPerson(firstName, lastName, email, true); } var personRecordTypeId = DefinedValueCache.Get(SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid()).Id; var personStatusPending = DefinedValueCache.Get(SystemGuid.DefinedValue.PERSON_RECORD_STATUS_PENDING.AsGuid()).Id; rockContext.WrapTransaction(() => { // If not an existing person, create a new one if (person == null) { person = new Person(); person.IsSystem = false; person.RecordTypeValueId = personRecordTypeId; person.RecordStatusValueId = personStatusPending; person.FirstName = firstName; person.LastName = lastName; person.Email = email; person.IsEmailActive = true; person.EmailPreference = EmailPreference.EmailAllowed; person.Gender = Gender.Unknown; if (person != null) { PersonService.SaveNewPerson(person, rockContext, null, false); } } if (person != null) { int typeId = EntityTypeCache.Get(typeof(Facebook)).Id; user = UserLoginService.Create(rockContext, person, AuthenticationServiceType.External, typeId, userName, "Twitter", true); } }); } if (user != null) { username = user.UserName; if (user.PersonId.HasValue) { var converter = new ExpandoObjectConverter(); var personService = new PersonService(rockContext); var person = personService.Get(user.PersonId.Value); if (person != null) { string twitterImageUrl = twitterUser.profile_image_url; bool twitterImageDefault = twitterUser.default_profile_image; twitterImageUrl = twitterImageUrl.Replace("_normal", ""); // If person does not have a photo, use their Twitter photo if it exists if (!person.PhotoId.HasValue && !twitterImageDefault && !string.IsNullOrWhiteSpace(twitterImageUrl)) { // Download the photo from the URL provided var restClient = new RestClient(twitterImageUrl); var restRequest = new RestRequest(Method.GET); var restResponse = restClient.Execute(restRequest); if (restResponse.StatusCode == HttpStatusCode.OK) { var bytes = restResponse.RawBytes; // Create and save the image BinaryFileType fileType = new BinaryFileTypeService(rockContext).Get(Rock.SystemGuid.BinaryFiletype.PERSON_IMAGE.AsGuid()); if (fileType != null) { var binaryFileService = new BinaryFileService(rockContext); var binaryFile = new BinaryFile(); binaryFileService.Add(binaryFile); binaryFile.IsTemporary = false; binaryFile.BinaryFileType = fileType; binaryFile.MimeType = "image/jpeg"; binaryFile.FileName = user.Person.NickName + user.Person.LastName + ".jpg"; binaryFile.FileSize = bytes.Length; binaryFile.ContentStream = new MemoryStream(bytes); rockContext.SaveChanges(); person.PhotoId = binaryFile.Id; rockContext.SaveChanges(); } } } // Save the Twitter social media link var twitterAttribute = AttributeCache.Get(Rock.SystemGuid.Attribute.PERSON_TWITTER.AsGuid()); if (twitterAttribute != null) { person.LoadAttributes(rockContext); person.SetAttributeValue(twitterAttribute.Key, twitterLink); person.SaveAttributeValues(rockContext); } } } } return(username); } }
/// <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 From value int? fromId = null; Guid?fromGuid = GetAttributeValue(action, "From").AsGuidOrNull(); if (fromGuid.HasValue) { var fromValue = DefinedValueCache.Get(fromGuid.Value, rockContext); if (fromValue != null) { fromId = fromValue.Id; } } // Get the recipients var recipients = new List <RecipientData>(); string toValue = GetAttributeValue(action, "To"); Guid guid = toValue.AsGuid(); if (!guid.IsEmpty()) { var attribute = AttributeCache.Get(guid, rockContext); if (attribute != null) { string toAttributeValue = action.GetWorklowAttributeValue(guid); if (!string.IsNullOrWhiteSpace(toAttributeValue)) { switch (attribute.FieldType.Class) { case "Rock.Field.Types.TextFieldType": { recipients.Add(new RecipientData(toAttributeValue, mergeFields)); break; } case "Rock.Field.Types.PersonFieldType": { Guid personAliasGuid = toAttributeValue.AsGuid(); if (!personAliasGuid.IsEmpty()) { var phoneNumber = new PersonAliasService(rockContext).Queryable() .Where(a => a.Guid.Equals(personAliasGuid)) .SelectMany(a => a.Person.PhoneNumbers) .Where(p => p.IsMessagingEnabled) .FirstOrDefault(); if (phoneNumber == null) { action.AddLogEntry("Invalid Recipient: Person or valid SMS phone number not found", true); } else { string smsNumber = phoneNumber.Number; if (!string.IsNullOrWhiteSpace(phoneNumber.CountryCode)) { smsNumber = "+" + phoneNumber.CountryCode + phoneNumber.Number; } var recipient = new RecipientData(smsNumber, mergeFields); recipients.Add(recipient); var person = new PersonAliasService(rockContext).GetPerson(personAliasGuid); if (person != null) { recipient.MergeFields.Add("Person", person); } } } break; } case "Rock.Field.Types.GroupFieldType": case "Rock.Field.Types.SecurityRoleFieldType": { int? groupId = toAttributeValue.AsIntegerOrNull(); Guid?groupGuid = toAttributeValue.AsGuidOrNull(); IQueryable <GroupMember> qry = null; // Handle situations where the attribute value is the ID if (groupId.HasValue) { qry = new GroupMemberService(rockContext).GetByGroupId(groupId.Value); } // Handle situations where the attribute value stored is the Guid else if (groupGuid.HasValue) { qry = new GroupMemberService(rockContext).GetByGroupGuid(groupGuid.Value); } else { action.AddLogEntry("Invalid Recipient: No valid group id or Guid", true); } if (qry != null) { foreach (var person in qry .Where(m => m.GroupMemberStatus == GroupMemberStatus.Active) .Select(m => m.Person)) { var phoneNumber = person.PhoneNumbers .Where(p => p.IsMessagingEnabled) .FirstOrDefault(); if (phoneNumber != null) { string smsNumber = phoneNumber.Number; if (!string.IsNullOrWhiteSpace(phoneNumber.CountryCode)) { smsNumber = "+" + phoneNumber.CountryCode + phoneNumber.Number; } var recipientMergeFields = new Dictionary <string, object>(mergeFields); var recipient = new RecipientData(smsNumber, recipientMergeFields); recipients.Add(recipient); recipient.MergeFields.Add("Person", person); } } } break; } } } } } else { if (!string.IsNullOrWhiteSpace(toValue)) { recipients.Add(new RecipientData(toValue.ResolveMergeFields(mergeFields), mergeFields)); } } // Get the message string message = GetAttributeValue(action, "Message"); Guid? messageGuid = message.AsGuidOrNull(); if (messageGuid.HasValue) { var attribute = AttributeCache.Get(messageGuid.Value, rockContext); if (attribute != null) { string messageAttributeValue = action.GetWorklowAttributeValue(messageGuid.Value); if (!string.IsNullOrWhiteSpace(messageAttributeValue)) { if (attribute.FieldType.Class == "Rock.Field.Types.TextFieldType" || attribute.FieldType.Class == "Rock.Field.Types.MemoFieldType") { message = messageAttributeValue; } } } } // Add the attachment (if one was specified) var binaryFile = new BinaryFileService(rockContext).Get(GetAttributeValue(action, "Attachment", true).AsGuid()); // Send the message if (recipients.Any() && !string.IsNullOrWhiteSpace(message)) { var smsMessage = new RockSMSMessage(); smsMessage.SetRecipients(recipients); smsMessage.FromNumber = DefinedValueCache.Get(fromId.Value); smsMessage.Message = message; if (binaryFile != null) { smsMessage.Attachments.Add(binaryFile); } smsMessage.Send(); } return(true); }
/// <summary> /// Creates the dynamic controls. /// </summary> /// <param name="groupMember">The group member.</param> private void CreateDynamicControls(GroupMember groupMember) { groupMember.LoadAttributes(); groupMember.Group.LoadAttributes(); // GroupMember Attributes (all of them) phGroupMemberAttributes.Controls.Clear(); // Exclude any attributes for which the current person has NO EDIT access. // But skip these three special member attributes since they are handled in a special way. List <string> excludes = groupMember.Attributes.Where( a => !a.Value.IsAuthorized(Rock.Security.Authorization.EDIT, this.CurrentPerson) && a.Key != "IndividualFundraisingGoal" && a.Key != "DisablePublicContributionRequests" && a.Key != "PersonalOpportunityIntroduction") .Select(a => a.Key).ToList(); if (!groupMember.Group.GetAttributeValue("AllowIndividualDisablingofContributionRequests").AsBoolean()) { excludes.Add("DisablePublicContributionRequests"); } if (!groupMember.Group.GetAttributeValue("AllowIndividualEditingofFundraisingGoal").AsBoolean()) { excludes.Add("IndividualFundraisingGoal"); } Rock.Attribute.Helper.AddEditControls(groupMember, phGroupMemberAttributes, true, "vgProfileEdit", excludes, true); // Person Attributes (the ones they picked in the Block Settings) phPersonAttributes.Controls.Clear(); var personAttributes = this.GetAttributeValue("PersonAttributes").SplitDelimitedValues().AsGuidList().Select(a => AttributeCache.Get(a)); if (personAttributes.Any()) { var person = groupMember.Person; person.LoadAttributes(); foreach (var personAttribute in personAttributes.OrderBy(a => a.Order)) { personAttribute.AddControl(phPersonAttributes.Controls, person.GetAttributeValue(personAttribute.Key), "vgProfileEdit", true, true); } } }
/// <summary> /// Sorts the object by the specified sort property. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source">The source.</param> /// <param name="sortProperty">The sort property.</param> /// <returns></returns> public static IOrderedQueryable <T> Sort <T>(this IQueryable <T> source, Rock.Web.UI.Controls.SortProperty sortProperty) { if (sortProperty.Property.StartsWith("attribute:")) { var itemType = typeof(T); var attributeCache = AttributeCache.Get(sortProperty.Property.Substring(10).AsInteger()); if (attributeCache != null && typeof(IModel).IsAssignableFrom(typeof(T))) { var entityIds = new List <int>(); var models = new List <IModel>(); source.ToList().ForEach(i => models.Add(i as IModel)); var ids = models.Select(m => m.Id).ToList(); var field = attributeCache.FieldType.Field; using (var rockContext = new RockContext()) { foreach (var attributeValue in new AttributeValueService(rockContext) .Queryable().AsNoTracking() .Where(v => v.AttributeId == attributeCache.Id && v.EntityId.HasValue && ids.Contains(v.EntityId.Value)) .ToList()) { var model = models.FirstOrDefault(m => m.Id == attributeValue.EntityId.Value); if (model != null) { model.CustomSortValue = field.SortValue(null, attributeValue.Value, attributeCache.QualifierValues); } } } var result = new List <T>(); if (sortProperty.Direction == SortDirection.Ascending) { models.OrderBy(m => m.CustomSortValue).ToList().ForEach(m => result.Add((T)m)); } else { models.OrderByDescending(m => m.CustomSortValue).ToList().ForEach(m => result.Add((T)m)); } return(result.AsQueryable().OrderBy(r => 0)); } } string[] columns = sortProperty.Property.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); IOrderedQueryable <T> qry = null; for (int columnIndex = 0; columnIndex < columns.Length; columnIndex++) { string column = columns[columnIndex].Trim(); var direction = sortProperty.Direction; if (column.ToLower().EndsWith(" desc")) { column = column.Left(column.Length - 5); direction = sortProperty.Direction == SortDirection.Ascending ? SortDirection.Descending : SortDirection.Ascending; } if (direction == SortDirection.Ascending) { qry = (columnIndex == 0) ? source.OrderBy(column) : qry.ThenBy(column); } else { qry = (columnIndex == 0) ? source.OrderByDescending(column) : qry.ThenByDescending(column); } } return(qry); }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The workflow action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns>true if successful; false otherwise</returns> public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages) { errorMessages = new List <string>(); Guid? parentGroupGuid = null; Guid? campusGuid = null; Campus campus = null; Group group = null; // get the campus attribute Guid campusAttributeGuid = GetAttributeValue(action, "Campus").AsGuid(); if (!campusAttributeGuid.IsEmpty()) { campusGuid = action.GetWorklowAttributeValue(campusAttributeGuid).AsGuidOrNull(); if (campusGuid.HasValue) { campus = new CampusService(rockContext).Get(campusGuid.Value); if (campus == null) { errorMessages.Add("The campus provided does not exist."); return(false); } } else { action.AddLogEntry("A campus was not provided, so the GetGroupChildGroupForCampus action will not continue."); return(true); } } else { errorMessages.Add("Invalid campus attribute provided."); return(false); } // stored as GroupTypeGuid|GroupGuid var parentGroupValues = (GetAttributeValue(action, "ParentGroup") ?? string.Empty).Split('|'); if (parentGroupValues.Count() > 1) { parentGroupGuid = parentGroupValues[1].AsGuidOrNull(); if (parentGroupGuid.HasValue) { // Find the child group of the given parent group that matches the campus id group = new GroupService(rockContext).Queryable().AsNoTracking() .Where(g => g.Guid == parentGroupGuid.Value) .SelectMany(g => g.Groups) .FirstOrDefault(cg => cg.CampusId == campus.Id); } } if (group != null) { // get the group attribute where we'll store the matching group. var groupAttribute = AttributeCache.Get(GetAttributeValue(action, "Group").AsGuid(), rockContext); if (groupAttribute != null) { SetWorkflowAttributeValue(action, groupAttribute.Guid, group.Guid.ToStringSafe()); action.AddLogEntry(string.Format("Set '{0}' attribute to '{1}'.", groupAttribute.Name, group.Guid)); } else { errorMessages.Add("Invalid group attribute provided."); return(false); } } else { action.AddLogEntry(string.Format("A child group of parent group '{0}' matching campus {1} could not be found.", parentGroupGuid, campus.Name)); } return(true); }
/// <summary> /// Completes the form action based on the action selected by the user. /// </summary> /// <param name="action">The action.</param> /// <param name="formAction">The form action.</param> /// <param name="currentPerson">The current person.</param> /// <param name="rockContext">The rock context.</param> /// <returns></returns> private string CompleteFormAction(WorkflowAction action, string formAction, Person currentPerson, RockContext rockContext) { var workflowService = new WorkflowService(rockContext); var activity = action.Activity; var workflow = activity.Workflow; var mergeFields = RequestContext.GetCommonMergeFields(currentPerson); mergeFields.Add("Action", action); mergeFields.Add("Activity", activity); mergeFields.Add("Workflow", workflow); Guid activityTypeGuid = Guid.Empty; string responseText = "Your information has been submitted successfully."; // // Get the target activity type guid and response text from the // submitted form action. // foreach (var act in action.ActionTypeCache.WorkflowForm.Actions.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { var actionDetails = act.Split(new char[] { '^' }); if (actionDetails.Length > 0 && actionDetails[0] == formAction) { if (actionDetails.Length > 2) { activityTypeGuid = actionDetails[2].AsGuid(); } if (actionDetails.Length > 3 && !string.IsNullOrWhiteSpace(actionDetails[3])) { responseText = actionDetails[3].ResolveMergeFields(mergeFields); } break; } } action.MarkComplete(); action.FormAction = formAction; action.AddLogEntry("Form Action Selected: " + action.FormAction); if (action.ActionTypeCache.IsActivityCompletedOnSuccess) { action.Activity.MarkComplete(); } // // Set the attribute that should contain the submitted form action. // if (action.ActionTypeCache.WorkflowForm.ActionAttributeGuid.HasValue) { var attribute = AttributeCache.Get(action.ActionTypeCache.WorkflowForm.ActionAttributeGuid.Value); if (attribute != null) { IHasAttributes item = null; if (attribute.EntityTypeId == workflow.TypeId) { item = workflow; } else if (attribute.EntityTypeId == activity.TypeId) { item = activity; } if (item != null) { item.SetAttributeValue(attribute.Key, formAction); } } } // // Activate the requested activity if there was one. // if (!activityTypeGuid.IsEmpty()) { var activityType = workflow.WorkflowTypeCache.ActivityTypes.Where(a => a.Guid.Equals(activityTypeGuid)).FirstOrDefault(); if (activityType != null) { WorkflowActivity.Activate(activityType, workflow); } } return(responseText); }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { btnExportToFinancialEdge.Text = GetAttributeValue("ButtonText"); var monthsBack = GetAttributeValue("MonthsBack").AsInteger() * -1; var firstBatchDate = RockDateTime.Now.AddMonths(monthsBack); var batchIdList = new List <int>(); var filteredBatchIdList = new List <int>(); var batchesToExport = new List <BatchData>(); using (var rockContextBatches = new RockContext()) { var batchService = new FinancialBatchService(rockContextBatches); var qry = batchService .Queryable().AsNoTracking() .Where(b => b.BatchStartDateTime.HasValue) .Where(b => b.BatchStartDateTime >= firstBatchDate) .Where(b => b.ControlAmount == b.Transactions.Sum(t => t.TransactionDetails.Sum(d => d.Amount))); string dateRangeValue = gfBatchesToExportFilter.GetUserPreference("Date Range"); if (!string.IsNullOrWhiteSpace(dateRangeValue)) { var drp = new DateRangePicker(); drp.DelimitedValues = dateRangeValue; if (drp.LowerValue.HasValue) { qry = qry.Where(b => b.BatchStartDateTime >= drp.LowerValue.Value); } if (drp.UpperValue.HasValue) { var endOfDay = drp.UpperValue.Value.AddDays(1); qry = qry.Where(b => b.BatchStartDateTime < endOfDay); } } var status = gfBatchesToExportFilter.GetUserPreference("Status").ConvertToEnumOrNull <BatchStatus>(); if (status.HasValue) { qry = qry.Where(b => b.Status == status); } SortProperty sortProperty = gBatchesToExport.SortProperty; if (sortProperty != null) { qry = qry.Sort(sortProperty); } else { qry = qry .OrderByDescending(b => b.BatchStartDateTime) .ThenBy(b => b.Name); } batchIdList = qry.Select(b => b.Id).ToList(); } using (var rockContextAttributeValues = new RockContext()) { var dateExportedAttributeId = AttributeCache.Get("16EFE0B4-E607-4960-BC92-8D66854E827A".AsGuid()).Id; //rocks.kfs.FinancialEdge.DateExported foreach (var batchId in batchIdList) { var attributeValue = new AttributeValueService(rockContextAttributeValues).GetByAttributeIdAndEntityId(dateExportedAttributeId, batchId); if (attributeValue == null || attributeValue.ValueAsDateTime == null) { filteredBatchIdList.Add(batchId); } } } using (var rockContextBatchData = new RockContext()) { foreach (var batchId in filteredBatchIdList) { var batch = new FinancialBatchService(rockContextBatchData).Get(batchId); batchesToExport.Add(new BatchData { Id = batch.Id, BatchStartDateTime = batch.BatchStartDateTime, Name = batch.Name, Status = batch.Status.ToString(), Note = batch.Note, Transactions = batch.Transactions.Count, Total = batch.GetTotalTransactionAmount(rockContextBatchData) }); } } gBatchesToExport.DataSource = batchesToExport; gBatchesToExport.ObjectList = ((List <BatchData>)gBatchesToExport.DataSource).ToDictionary(b => b.Id.ToString(), v => v as object); gBatchesToExport.EntityTypeId = EntityTypeCache.Get <FinancialBatch>().Id; gBatchesToExport.DataBind(); }
public WorkflowForm GetNextForm(int?workflowId = null, string formAction = null, List <MobileField> formFields = null) { var rockContext = new RockContext(); var workflowService = new WorkflowService(rockContext); var workflow = LoadWorkflow(workflowId, rockContext); var currentPerson = GetCurrentPerson(); var action = ProcessAndGetNextAction(workflow, currentPerson, rockContext, out var message); if (action == null) { return(new WorkflowForm { Message = message ?? GetCompletionMessage(workflow, string.Empty) }); } // // If this is a form submittal, then complete the form and re-process. // if (!string.IsNullOrEmpty(formAction) && formFields != null) { SetFormValues(action, formFields); var responseText = CompleteFormAction(action, formAction, currentPerson, rockContext); action = ProcessAndGetNextAction(workflow, currentPerson, rockContext, out message); if (action == null) { return(new WorkflowForm { Message = message ?? GetCompletionMessage(workflow, responseText) }); } } // // Begin building up the response with the form data. // var activity = action.Activity; var form = action.ActionTypeCache.WorkflowForm; var mobileForm = new WorkflowForm { WorkflowId = workflow.Id }; // // Populate all the form fields that should be visible on the workflow. // foreach (var formAttribute in form.FormAttributes.OrderBy(a => a.Order)) { if (formAttribute.IsVisible) { var attribute = AttributeCache.Get(formAttribute.AttributeId); string value = attribute.DefaultValue; // // Get the current value from either the workflow or the activity. // if (workflow.AttributeValues.ContainsKey(attribute.Key) && workflow.AttributeValues[attribute.Key] != null) { value = workflow.AttributeValues[attribute.Key].Value; } else if (activity.AttributeValues.ContainsKey(attribute.Key) && activity.AttributeValues[attribute.Key] != null) { value = activity.AttributeValues[attribute.Key].Value; } var mobileField = new MobileField { AttributeId = attribute.Id, Key = attribute.Key, Title = attribute.Name, IsRequired = formAttribute.IsRequired, ConfigurationValues = attribute.QualifierValues.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Value), RockFieldType = attribute.FieldType.Class, Value = value }; if (formAttribute.IsReadOnly) { var field = attribute.FieldType.Field; string formattedValue = null; // get formatted value if (attribute.FieldType.Class == typeof(Rock.Field.Types.ImageFieldType).FullName) { formattedValue = field.FormatValueAsHtml(null, attribute.EntityTypeId, activity.Id, value, attribute.QualifierValues, true); } else { formattedValue = field.FormatValueAsHtml(null, attribute.EntityTypeId, activity.Id, value, attribute.QualifierValues); } mobileField.Value = formattedValue; mobileField.RockFieldType = string.Empty; if (formAttribute.HideLabel) { mobileField.Title = string.Empty; } } mobileForm.Fields.Add(mobileField); } } // // Build the list of form actions (buttons) that should be presented // to the user. // foreach (var btn in form.Actions.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { var actionDetails = btn.Split(new char[] { '^' }); if (actionDetails.Length > 0) { var btnType = DefinedValueCache.Get(actionDetails[1].AsGuid()); if (btnType != null) { mobileForm.Buttons.Add(new WorkflowFormButton { Text = actionDetails[0], Type = btnType.Value }); } } } return(mobileForm); }
/// <summary> /// Binds the attributes. /// </summary> private void BindAttributes(Group _group) { var bypassSecurity = GetAttributeValue("BypassAttributeSecurity").AsBoolean(); // Parse the attribute filters AvailableAttributes = new List <AttributeCache>(); if (_group != null && _gmAttributeExport > 0) { // GROUP MEMBER ATTRIBUTES int gmEntityTypeId = new GroupMember().TypeId; string groupQualifier = _group.Id.ToString(); string groupTypeQualifier = _group.GroupTypeId.ToString(); foreach (var attributeModel in new AttributeService(new RockContext()).Queryable() .Where(a => a.EntityTypeId == gmEntityTypeId && (a.IsGridColumn || _gmAttributeExport == 1) && ((a.EntityTypeQualifierColumn.Equals("GroupId", StringComparison.OrdinalIgnoreCase) && a.EntityTypeQualifierValue.Equals(groupQualifier)) || (a.EntityTypeQualifierColumn.Equals("GroupTypeId", StringComparison.OrdinalIgnoreCase) && a.EntityTypeQualifierValue.Equals(groupTypeQualifier)))) .OrderByDescending(a => a.EntityTypeQualifierColumn) .ThenBy(a => a.Order) .ThenBy(a => a.Name)) { if (attributeModel.IsAuthorized(Authorization.VIEW, CurrentPerson) || bypassSecurity) { AvailableAttributes.Add(AttributeCache.Get(attributeModel)); } } // PERSON ATTRIBUTES var AvailablePersonAttributeIds = new List <int>(); if (_group.Attributes == null) { _group.LoadAttributes(); } if (_group.Attributes != null) { var attributeFieldTypeId = FieldTypeCache.Get(Rock.SystemGuid.FieldType.ATTRIBUTE).Id; var personAttributes = _group.Attributes.Values.FirstOrDefault(a => a.FieldTypeId == attributeFieldTypeId && a.QualifierValues.ContainsKey("entitytype") && a.QualifierValues.Values.Any(v => v.Value.Equals(Rock.SystemGuid.EntityType.PERSON, StringComparison.CurrentCultureIgnoreCase)) ); if (personAttributes != null) { var personAttributeValues = _group.GetAttributeValue(personAttributes.Key); foreach (var personAttribute in personAttributeValues.Split(',').AsGuidList()) { AvailablePersonAttributeIds.Add(AttributeCache.Get(personAttribute).Id); } } } int pEntityTypeId = new Person().TypeId; foreach (var attributeModel in new AttributeService(new RockContext()).Queryable() .Where(a => a.EntityTypeId == pEntityTypeId && AvailablePersonAttributeIds.Contains(a.Id) ) .OrderByDescending(a => a.EntityTypeQualifierColumn) .OrderBy(a => a.Order) .ThenBy(a => a.Name)) { if (attributeModel.IsAuthorized(Authorization.VIEW, CurrentPerson) || bypassSecurity) { AvailableAttributes.Add(AttributeCache.Get(attributeModel)); } } } }
/// <summary> /// Restores the view-state information from a previous user control request that was saved by the <see cref="M:System.Web.UI.UserControl.SaveViewState" /> method. /// </summary> /// <param name="savedState">An <see cref="T:System.Object" /> that represents the user control state to be restored.</param> protected override void LoadViewState(object savedState) { base.LoadViewState(savedState); if (ViewState["AvailableAttributeIds"] != null) { AvailableAttributes = (ViewState["AvailableAttributeIds"] as int[]).Select(a => AttributeCache.Get(a)).ToList(); } AddDynamicControls(); }