/// <summary> /// Creates a FamilyState object from the group /// </summary> /// <param name="group">The group.</param> /// <returns></returns> public static FamilyRegistrationState FromGroup(Group group) { FamilyRegistrationState familyState = new FamilyRegistrationState(); familyState.FamilyPersonListState = new List <FamilyRegistrationState.FamilyPersonState>(); group.LoadAttributes(); if (group.Id > 0) { familyState.GroupId = group.Id; familyState.FamilyName = group.Name; } else { familyState.FamilyName = "Add Family"; } familyState.FamilyAttributeValuesState = group.AttributeValues.ToDictionary(k => k.Key, v => v.Value); return(familyState); }
/// <summary> /// Saves the family and persons to the database /// </summary> /// <param name="kioskCampusId">The kiosk campus identifier.</param> /// <param name="rockContext">The rock context.</param> /// <returns></returns> public SaveResult SaveFamilyAndPersonsToDatabase(int?kioskCampusId, RockContext rockContext) { SaveResult saveResult = new SaveResult(); FamilyRegistrationState editFamilyState = this; var personService = new PersonService(rockContext); var groupService = new GroupService(rockContext); var recordTypePersonId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid()).Id; var maritalStatusMarried = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_MARITAL_STATUS_MARRIED.AsGuid()); var maritalStatusSingle = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_MARITAL_STATUS_SINGLE.AsGuid()); var numberTypeValueMobile = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_PHONE_TYPE_MOBILE.AsGuid()); int groupTypeRoleAdultId = GroupTypeCache.GetFamilyGroupType().Roles.FirstOrDefault(a => a.Guid == Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT.AsGuid()).Id; int groupTypeRoleChildId = GroupTypeCache.GetFamilyGroupType().Roles.FirstOrDefault(a => a.Guid == Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_CHILD.AsGuid()).Id; int?groupTypeRoleCanCheckInId = GroupTypeCache.Get(Rock.SystemGuid.GroupType.GROUPTYPE_KNOWN_RELATIONSHIPS.AsGuid()) ?.Roles.FirstOrDefault(r => r.Guid == Rock.SystemGuid.GroupRole.GROUPROLE_KNOWN_RELATIONSHIPS_CAN_CHECK_IN.AsGuid())?.Id; bool?groupTypeDefaultSmsEnabled = GroupTypeCache.GetFamilyGroupType().GetAttributeValue(Rock.SystemKey.GroupTypeAttributeKey.CHECKIN_REGISTRATION_DEFAULTSMSENABLED).AsBooleanOrNull(); Group primaryFamily = null; if (editFamilyState.GroupId.HasValue) { primaryFamily = groupService.Get(editFamilyState.GroupId.Value); } // see if we can find matches for new people that were added, and also set the primary family if this is a new family, but a matching family was found foreach (var familyPersonState in editFamilyState.FamilyPersonListState.Where(a => !a.PersonId.HasValue && !a.IsDeleted)) { var personQuery = new PersonService.PersonMatchQuery(familyPersonState.FirstName, familyPersonState.LastName, familyPersonState.Email, familyPersonState.MobilePhoneNumber, familyPersonState.Gender, familyPersonState.BirthDate, familyPersonState.SuffixValueId); var matchingPerson = personService.FindPerson(personQuery, true); if (matchingPerson != null) { // newly added person, but a match was found, so set the PersonId, GroupId, and ConnectionStatusValueID to the matching person instead of creating a new person familyPersonState.PersonId = matchingPerson.Id; familyPersonState.GroupId = matchingPerson.GetFamily(rockContext)?.Id; familyPersonState.RecordStatusValueId = matchingPerson.RecordStatusValueId; familyPersonState.ConnectionStatusValueId = matchingPerson.ConnectionStatusValueId; familyPersonState.ConvertedToMatchedPerson = true; if (primaryFamily == null && familyPersonState.IsAdult) { // if this is a new family, but we found a matching adult person, use that person's family as the family primaryFamily = matchingPerson.GetFamily(rockContext); } } } // loop thru all people and add/update as needed foreach (var familyPersonState in editFamilyState.FamilyPersonListState.Where(a => !a.IsDeleted)) { Person person; if (!familyPersonState.PersonId.HasValue) { person = new Person(); personService.Add(person); saveResult.NewPersonList.Add(person); person.RecordTypeValueId = recordTypePersonId; person.FirstName = familyPersonState.FirstName; } else { person = personService.Get(familyPersonState.PersonId.Value); } // NOTE, Gender, MaritalStatusValueId, NickName, LastName are required fields so, always updated them to match the UI (even if a matched person was found) person.Gender = familyPersonState.Gender; person.MaritalStatusValueId = familyPersonState.IsMarried ? maritalStatusMarried.Id : maritalStatusSingle.Id; person.NickName = familyPersonState.FirstName; person.LastName = familyPersonState.LastName; // if the familyPersonState was converted to a Matched Person, don't overwrite existing values with blank values var saveEmptyValues = !familyPersonState.ConvertedToMatchedPerson; if (familyPersonState.SuffixValueId.HasValue || saveEmptyValues) { person.SuffixValueId = familyPersonState.SuffixValueId; } if (familyPersonState.BirthDate.HasValue || saveEmptyValues) { person.SetBirthDate(familyPersonState.BirthDate); } if (familyPersonState.DeceasedDate.HasValue || saveEmptyValues) { person.DeceasedDate = familyPersonState.DeceasedDate; } if (familyPersonState.Email.IsNotNullOrWhiteSpace() || saveEmptyValues) { person.Email = familyPersonState.Email; } if (familyPersonState.GradeOffset.HasValue || saveEmptyValues) { person.GradeOffset = familyPersonState.GradeOffset; } // if a matching person was found, the familyPersonState's RecordStatusValueId and ConnectinoStatusValueId was already updated to match the matched person person.RecordStatusValueId = familyPersonState.RecordStatusValueId; person.ConnectionStatusValueId = familyPersonState.ConnectionStatusValueId; rockContext.SaveChanges(); bool isNewPerson = !familyPersonState.PersonId.HasValue; if (!familyPersonState.PersonId.HasValue) { // if we added a new person, we know now the personId after SaveChanges, so set it familyPersonState.PersonId = person.Id; } if (familyPersonState.AlternateID.IsNotNullOrWhiteSpace()) { PersonSearchKey personAlternateValueIdSearchKey; PersonSearchKeyService personSearchKeyService = new PersonSearchKeyService(rockContext); if (isNewPerson) { // if we added a new person, a default AlternateId was probably added in the service layer. If a specific Alternate ID was specified, make sure that their SearchKey is updated personAlternateValueIdSearchKey = person.GetPersonSearchKeys(rockContext).Where(a => a.SearchTypeValueId == _personSearchAlternateValueId).FirstOrDefault(); } else { // see if the key already exists. If if it doesn't already exist, let a new one get created personAlternateValueIdSearchKey = person.GetPersonSearchKeys(rockContext).Where(a => a.SearchTypeValueId == _personSearchAlternateValueId && a.SearchValue == familyPersonState.AlternateID).FirstOrDefault(); } if (personAlternateValueIdSearchKey == null) { personAlternateValueIdSearchKey = new PersonSearchKey(); personAlternateValueIdSearchKey.PersonAliasId = person.PrimaryAliasId; personAlternateValueIdSearchKey.SearchTypeValueId = _personSearchAlternateValueId; personSearchKeyService.Add(personAlternateValueIdSearchKey); } if (personAlternateValueIdSearchKey.SearchValue != familyPersonState.AlternateID) { personAlternateValueIdSearchKey.SearchValue = familyPersonState.AlternateID; rockContext.SaveChanges(); } } person.LoadAttributes(); foreach (var attributeValue in familyPersonState.PersonAttributeValuesState) { // only set attribute values that are editable so we don't accidently delete any attribute values if (familyPersonState.EditableAttributes.Contains(attributeValue.Value.AttributeId)) { if (attributeValue.Value.Value.IsNotNullOrWhiteSpace() || saveEmptyValues) { person.SetAttributeValue(attributeValue.Key, attributeValue.Value.Value); } } } person.SaveAttributeValues(rockContext); if (familyPersonState.MobilePhoneNumber.IsNotNullOrWhiteSpace() || saveEmptyValues) { person.UpdatePhoneNumber(numberTypeValueMobile.Id, familyPersonState.MobilePhoneCountryCode, familyPersonState.MobilePhoneNumber, familyPersonState.MobilePhoneSmsEnabled ?? groupTypeDefaultSmsEnabled, false, rockContext); } rockContext.SaveChanges(); } if (primaryFamily == null) { // new family and no family found by looking up matching adults, so create a new family primaryFamily = new Group(); var familyLastName = editFamilyState.FamilyPersonListState.OrderBy(a => a.IsAdult).Where(a => !a.IsDeleted).Select(a => a.LastName).FirstOrDefault(); primaryFamily.Name = familyLastName + " Family"; primaryFamily.GroupTypeId = GroupTypeCache.GetFamilyGroupType().Id; // Set the Campus to the Campus of this Kiosk primaryFamily.CampusId = kioskCampusId; groupService.Add(primaryFamily); saveResult.NewFamilyList.Add(primaryFamily); rockContext.SaveChanges(); } if (!editFamilyState.GroupId.HasValue) { editFamilyState.GroupId = primaryFamily.Id; } primaryFamily.LoadAttributes(); foreach (var familyAttribute in editFamilyState.FamilyAttributeValuesState) { // only set attribute values that are editable so we don't accidently delete any attribute values if (editFamilyState.EditableFamilyAttributes.Contains(familyAttribute.Value.AttributeId)) { primaryFamily.SetAttributeValue(familyAttribute.Key, familyAttribute.Value.Value); } } primaryFamily.SaveAttributeValues(rockContext); var groupMemberService = new GroupMemberService(rockContext); // loop thru all people that are part of the same family (in the UI) and ensure they are all in the same primary family (in the database) foreach (var familyPersonState in editFamilyState.FamilyPersonListState.Where(a => !a.IsDeleted && a.InPrimaryFamily)) { var currentFamilyMember = primaryFamily.Members.FirstOrDefault(m => m.PersonId == familyPersonState.PersonId.Value); if (currentFamilyMember == null) { currentFamilyMember = new GroupMember { GroupId = primaryFamily.Id, PersonId = familyPersonState.PersonId.Value, GroupMemberStatus = GroupMemberStatus.Active }; if (familyPersonState.IsAdult) { currentFamilyMember.GroupRoleId = groupTypeRoleAdultId; } else { currentFamilyMember.GroupRoleId = groupTypeRoleChildId; } groupMemberService.Add(currentFamilyMember); rockContext.SaveChanges(); } } // make a dictionary of new related families (by lastname) so we can combine any new related children into a family with the same last name Dictionary <string, Group> newRelatedFamilies = new Dictionary <string, Group>(StringComparer.OrdinalIgnoreCase); // loop thru all people that are NOT part of the same family foreach (var familyPersonState in editFamilyState.FamilyPersonListState.Where(a => !a.IsDeleted && a.InPrimaryFamily == false)) { if (!familyPersonState.GroupId.HasValue) { // related person not in a family yet Group relatedFamily = newRelatedFamilies.GetValueOrNull(familyPersonState.LastName); if (relatedFamily == null) { relatedFamily = new Group(); relatedFamily.Name = familyPersonState.LastName + " Family"; relatedFamily.GroupTypeId = GroupTypeCache.GetFamilyGroupType().Id; // Set the Campus to the Campus of this Kiosk relatedFamily.CampusId = kioskCampusId; newRelatedFamilies.Add(familyPersonState.LastName, relatedFamily); groupService.Add(relatedFamily); saveResult.NewFamilyList.Add(relatedFamily); } rockContext.SaveChanges(); familyPersonState.GroupId = relatedFamily.Id; var familyMember = new GroupMember { GroupId = relatedFamily.Id, PersonId = familyPersonState.PersonId.Value, GroupMemberStatus = GroupMemberStatus.Active }; if (familyPersonState.IsAdult) { familyMember.GroupRoleId = groupTypeRoleAdultId; } else { familyMember.GroupRoleId = groupTypeRoleChildId; } groupMemberService.Add(familyMember); } // ensure there are known relationships between each adult in the primary family to this person that isn't in the primary family foreach (var primaryFamilyAdult in editFamilyState.FamilyPersonListState.Where(a => a.IsAdult && a.InPrimaryFamily)) { groupMemberService.CreateKnownRelationship(primaryFamilyAdult.PersonId.Value, familyPersonState.PersonId.Value, familyPersonState.ChildRelationshipToAdult); // if this is something other than the CanCheckIn relationship, but is a relationship that should ensure a CanCheckIn relationship, create a CanCheckinRelationship if (groupTypeRoleCanCheckInId.HasValue && familyPersonState.CanCheckIn && groupTypeRoleCanCheckInId != familyPersonState.ChildRelationshipToAdult) { groupMemberService.CreateKnownRelationship(primaryFamilyAdult.PersonId.Value, familyPersonState.PersonId.Value, groupTypeRoleCanCheckInId.Value); } } } return(saveResult); }