/// <summary> /// Should the achievement type process attempts if the given source entity has been modified in some way. /// </summary> /// <param name="achievementTypeCache">The achievement type cache.</param> /// <param name="sourceEntity">The source entity.</param> /// <returns></returns> public override bool ShouldProcess(AchievementTypeCache achievementTypeCache, IEntity sourceEntity) { var interaction = sourceEntity as Interaction; if (interaction == null) { return(false); } var channel = GetInteractionChannelCache(achievementTypeCache); if (channel == null) { return(true); } var component = GetInteractionComponentCache(achievementTypeCache); if (component == null) { component = InteractionComponentCache.Get(interaction.InteractionComponentId); return(component.InteractionChannelId == channel.Id); } return(interaction.InteractionComponentId == component.Id); }
/// <summary> /// Gets the models from the delimited values. /// </summary> /// <param name="value">The value.</param> /// <param name="interactionChannel">The interactionChannel</param> /// <param name="interactionComponent">The interactionComponent</param> private void GetModelsFromAttributeValue(string value, out InteractionChannelCache interactionChannel, out InteractionComponentCache interactionComponent) { interactionChannel = null; interactionComponent = null; ParseDelimitedGuids(value, out var interactionChannelGuid, out var interactionComponentGuid); if (interactionChannelGuid.HasValue || interactionComponentGuid.HasValue) { if (interactionChannelGuid.HasValue) { interactionChannel = InteractionChannelCache.Get(interactionChannelGuid.Value); } if (interactionComponentGuid.HasValue) { interactionComponent = InteractionComponentCache.Get(interactionComponentGuid.Value); } } }
/// <summary> /// Reads new values entered by the user for the field ( as Guid ) /// </summary> /// <param name="control">Parent control that controls were added to in the CreateEditControl() method</param> /// <param name="configurationValues">The configuration values.</param> /// <returns></returns> public override string GetEditValue(Control control, Dictionary <string, ConfigurationValue> configurationValues) { var interactionChannelInteractionComponentPicker = control as InteractionChannelInteractionComponentPicker; if (interactionChannelInteractionComponentPicker != null) { var rockContext = new RockContext(); Guid?interactionChannelGuid = null; Guid?interactionComponentGuid = null; if (interactionChannelInteractionComponentPicker.InteractionChannelId.HasValue) { var channel = InteractionChannelCache.Get(interactionChannelInteractionComponentPicker.InteractionChannelId.Value); if (channel != null) { interactionChannelGuid = channel.Guid; } } if (interactionChannelInteractionComponentPicker.InteractionComponentId.HasValue) { var component = InteractionComponentCache.Get(interactionChannelInteractionComponentPicker.InteractionComponentId.Value); if (component != null) { interactionComponentGuid = component.Guid; } } if (interactionChannelGuid.HasValue || interactionComponentGuid.HasValue) { return(string.Format("{0}|{1}", interactionChannelGuid, interactionComponentGuid)); } } return(null); }
/// <summary> /// BulkInserts Interaction Records /// </summary> /// <remarks> /// If any PersonAliasId references a PersonAliasId record that doesn't exist, the field value will be set to null. /// Also, if the InteractionComponent Id (or Guid) is specified, but references a Interaction Component record that doesn't exist /// the Interaction will not be recorded. /// </remarks> /// <param name="interactionsImport">The interactions import.</param> internal static void BulkInteractionImport(InteractionsImport interactionsImport) { if (interactionsImport == null) { throw new Exception("InteractionsImport must be assigned a value."); } var interactionImportList = interactionsImport.Interactions; if (interactionImportList == null || !interactionImportList.Any()) { // if there aren't any return return; } /* 2020-05-14 MDP * Make sure that all the PersonAliasIds in the import exist in the database. * For performance reasons, look them up all at one and keep a list of valid ones. * * If there are any PersonAliasIds that aren't valid, * we decided that just set the PersonAliasId to null (we want ignore bad data). */ HashSet <int> validPersonAliasIds = interactionsImport.GetValidPersonAliasIds(); List <Interaction> interactionsToInsert = new List <Interaction>(); foreach (InteractionImport interactionImport in interactionImportList) { if (interactionImport.Interaction == null) { throw new ArgumentNullException("InteractionImport.Interaction can not be null"); } // Determine which Channel this should be set to if (interactionImport.InteractionChannelId.HasValue) { // make sure it is a valid Id interactionImport.InteractionChannelId = InteractionChannelCache.Get(interactionImport.InteractionChannelId.Value)?.Id; } // Determine which Channel Type Medium this should be set to if (interactionImport.InteractionChannelChannelTypeMediumValueId.HasValue) { // make sure it is a valid Id interactionImport.InteractionChannelChannelTypeMediumValueId = DefinedValueCache.Get(interactionImport.InteractionChannelChannelTypeMediumValueId.Value)?.Id; } if (!interactionImport.InteractionChannelChannelTypeMediumValueId.HasValue) { if (interactionImport.InteractionChannelChannelTypeMediumValueGuid.HasValue) { interactionImport.InteractionChannelChannelTypeMediumValueId = DefinedValueCache.GetId(interactionImport.InteractionChannelChannelTypeMediumValueGuid.Value); } } if (!interactionImport.InteractionChannelId.HasValue) { if (interactionImport.InteractionChannelGuid.HasValue) { interactionImport.InteractionChannelId = InteractionChannelCache.GetId(interactionImport.InteractionChannelGuid.Value); } // if InteractionChannelId is still null, lookup (or create) an InteractionChannel from InteractionChannelForeignKey (if it is specified) if (interactionImport.InteractionChannelId == null && interactionImport.InteractionChannelForeignKey.IsNotNullOrWhiteSpace()) { interactionImport.InteractionChannelId = InteractionChannelCache.GetCreateChannelIdByForeignKey(interactionImport.InteractionChannelForeignKey, interactionImport.InteractionChannelName, interactionImport.InteractionChannelChannelTypeMediumValueId); } else { /* 2020-05-14 MDP * Discussed this and decided that if we tried InteractionChannelId and InteractionChannelGuid, and InteractionChannelForeignKey was not specified, * we'll just skip over this record */ continue; } } // Determine which Component this should be set to if (interactionImport.InteractionComponentId.HasValue) { // make sure it is a valid Id interactionImport.InteractionComponentId = InteractionComponentCache.Get(interactionImport.InteractionComponentId.Value)?.Id; } if (!interactionImport.InteractionComponentId.HasValue) { if (interactionImport.InteractionComponentGuid.HasValue) { interactionImport.InteractionComponentId = InteractionComponentCache.GetId(interactionImport.InteractionComponentGuid.Value); } // if InteractionComponentId is still null, lookup (or create) an InteractionComponent from the ForeignKey and ChannelId if (interactionImport.InteractionComponentForeignKey.IsNotNullOrWhiteSpace()) { interactionImport.InteractionComponentId = InteractionComponentCache.GetComponentIdByForeignKeyAndChannelId( interactionImport.InteractionComponentForeignKey, interactionImport.InteractionChannelId.Value, interactionImport.InteractionComponentName); } else { /* 2020-05-14 MDP * Discussed this and decided that and if we tried InteractionComponentId and InteractionComponentGuid, and InteractionComponentForeignKey was not specified, * we'll just skip over this record */ continue; } } } foreach (InteractionImport interactionImport in interactionImportList.Where(a => a.InteractionComponentId.HasValue)) { Interaction interaction = new Interaction { InteractionComponentId = interactionImport.InteractionComponentId.Value }; interaction.InteractionDateTime = interactionImport.Interaction.InteractionDateTime; // if operation is over 25, truncate it interaction.Operation = interactionImport.Interaction.Operation.Truncate(25); interaction.InteractionComponentId = interactionImport.InteractionComponentId.Value; interaction.EntityId = interactionImport.Interaction.EntityId; if (interactionImport.Interaction.RelatedEntityTypeId.HasValue) { /* 2020-05-14 MDP * We want to ignore bad data, so first see if the RelatedEntityTypeId exists by looking it up in a cache. * If it doesn't exist, it'll set RelatedEntityTypeId to null (so that we don't get a database constraint error) */ interaction.RelatedEntityTypeId = EntityTypeCache.Get(interactionImport.Interaction.RelatedEntityTypeId.Value)?.Id; } interaction.RelatedEntityId = interactionImport.Interaction.RelatedEntityId; if (interactionImport.Interaction.PersonAliasId.HasValue) { /* 2020-05-14 MDP * We want to ignore bad data, so see if the specified PersonAliasId exists in the validPersonAliasIds that we lookup up * If it doesn't exist, we'll leave interaction.PersonAliasId null (so that we don't get a database constraint error) */ if (validPersonAliasIds.Contains(interactionImport.Interaction.PersonAliasId.Value)) { interaction.PersonAliasId = interactionImport.Interaction.PersonAliasId.Value; } } // BulkImport doesn't include Session information TODO??? interaction.InteractionSessionId = null; // if the summary is over 500 chars, truncate with addEllipsis=true interaction.InteractionSummary = interactionImport.Interaction.InteractionSummary.Truncate(500, true); interaction.InteractionData = interactionImport.Interaction.InteractionData; interaction.PersonalDeviceId = interactionImport.Interaction.PersonalDeviceId; interaction.InteractionEndDateTime = interactionImport.Interaction.InteractionEndDateTime; // Campaign related fields, we'll truncate those if they are too long interaction.Source = interactionImport.Interaction.Source.Truncate(25); interaction.Medium = interactionImport.Interaction.Medium.Truncate(25); interaction.Campaign = interactionImport.Interaction.Campaign.Truncate(50); interaction.Content = interactionImport.Interaction.Content.Truncate(50); interaction.Term = interactionImport.Interaction.Term.Truncate(50); interaction.ForeignId = interactionImport.Interaction.ForeignId; interaction.ForeignKey = interactionImport.Interaction.ForeignKey; interaction.ForeignGuid = interactionImport.Interaction.ForeignGuid; interaction.ChannelCustom1 = interactionImport.Interaction.ChannelCustom1.Truncate(500, true); interaction.ChannelCustom2 = interactionImport.Interaction.ChannelCustom2.Truncate(2000, true); interaction.ChannelCustomIndexed1 = interactionImport.Interaction.ChannelCustomIndexed1.Truncate(500, true); interaction.InteractionLength = interactionImport.Interaction.InteractionLength; interaction.InteractionTimeToServe = interactionImport.Interaction.InteractionTimeToServe; interactionsToInsert.Add(interaction); } using (var rockContext = new RockContext()) { rockContext.BulkInsert(interactionsToInsert); } // This logic is normally handled in the Interaction.PostSave method, but since the BulkInsert bypasses those // model hooks, streaks need to be updated here. Also, it is not necessary for this logic to complete before this // transaction can continue processing and exit, so update the streak using a task. // Only launch this task if there are StreakTypes configured that have interactions. Otherwise several // database calls are made only to find out there are no streak types defined. if (StreakTypeCache.All().Any(s => s.IsInteractionRelated)) { // Ids do not exit for the interactions in the collection since they were bulk imported. // Read their ids from their guids and append the id. var insertedGuids = interactionsToInsert.Select(i => i.Guid).ToList(); var interactionIds = new InteractionService(new RockContext()).Queryable() .Where(i => insertedGuids.Contains(i.Guid)) .Select(i => new { i.Id, i.Guid }) .ToList(); foreach (var interactionId in interactionIds) { var interaction = interactionsToInsert.Where(i => i.Guid == interactionId.Guid).FirstOrDefault(); if (interaction != null) { interaction.Id = interactionId.Id; } } // Launch task interactionsToInsert.ForEach(i => Task.Run(() => StreakTypeService.HandleInteractionRecord(i.Id))); } }
/// <summary> /// Gets the component. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="channel">The channel.</param> /// <param name="entityId">The entity identifier.</param> /// <param name="identifier">The identifier.</param> /// <returns></returns> private InteractionComponentCache GetComponent(RockContext rockContext, InteractionChannelCache channel, int?entityId, string identifier) { if (channel != null) { if (entityId.HasValue) { // Find by the Entity Id int?interactionComponentId = new InteractionComponentService(rockContext) .Queryable() .AsNoTracking() .Where(c => c.EntityId.HasValue && c.InteractionChannelId == channel.Id && c.EntityId.Value == entityId.Value) .Select(c => c.Id) .Cast <int?>() .FirstOrDefault(); if (interactionComponentId != null) { return(InteractionComponentCache.Get(interactionComponentId.Value)); } } if (identifier.IsNotNullOrWhiteSpace()) { // Find by Id int?id = identifier.AsIntegerOrNull(); if (id.HasValue) { var component = InteractionComponentCache.Get(id.Value); if (component != null && component.InteractionChannelId == channel.Id) { return(component); } } // Find by Guid Guid?guid = identifier.AsGuidOrNull(); if (guid.HasValue) { var component = InteractionComponentCache.Get(guid.Value); if (component != null && component.InteractionChannelId == channel.Id) { return(component); } } if (!id.HasValue && !guid.HasValue) { // Find by Name int?interactionComponentId = new InteractionComponentService(rockContext) .Queryable() .AsNoTracking() .Where(c => c.InteractionChannelId == channel.Id) .Where(c => c.Name.Equals(identifier, StringComparison.OrdinalIgnoreCase)) .Select(c => c.Id) .Cast <int?>() .FirstOrDefault(); if (interactionComponentId != null) { return(InteractionComponentCache.Get(interactionComponentId.Value)); } // If still no match, and we have a name, create a new channel using (var newRockContext = new RockContext()) { var interactionComponent = new InteractionComponent(); interactionComponent.Name = identifier; interactionComponent.InteractionChannelId = channel.Id; new InteractionComponentService(newRockContext).Add(interactionComponent); newRockContext.SaveChanges(); return(InteractionComponentCache.Get(interactionComponent.Id)); } } } } return(null); }
/// <summary> /// Gets the cache object associated with this Entity /// </summary> /// <returns></returns> public IEntityCache GetCacheObject() { return(InteractionComponentCache.Get(this.Id)); }
/// <summary> /// Gets the interaction component cache. /// </summary> /// <param name="achievementTypeCache">The achievement type cache.</param> /// <returns></returns> private InteractionComponentCache GetInteractionComponentCache(AchievementTypeCache achievementTypeCache) { var guid = GetInteractionComponentGuid(achievementTypeCache); return(guid.HasValue ? InteractionComponentCache.Get(guid.Value) : null); }