/// <summary> /// Get a query for people that have met prerequisites /// </summary> /// <param name="rockContext"></param> /// <param name="stepTypeView"></param> /// <returns></returns> private IQueryable <int> GetPersonIdsThatHaveMetPrerequisitesQuery(RockContext rockContext, StepTypeView stepTypeView) { var stepService = new StepService(rockContext); // We are querying for people that have met all the prerequisites for this step type // This method should not be called for stepTypes that do not have prerequisites // because that would be a query for everyone in the database var firstStepTypeId = stepTypeView.PrerequisiteStepTypeIds.First(); var prerequisiteCount = stepTypeView.PrerequisiteStepTypeIds.Count(); // Aliases that have completed the first prerequisite var query = stepService.Queryable().AsNoTracking() .Where(s => s.StepStatus.IsCompleteStatus && s.StepTypeId == firstStepTypeId) .Select(s => s.PersonAlias.PersonId); for (var i = 1; i < prerequisiteCount; i++) { var stepTypeId = stepTypeView.PrerequisiteStepTypeIds.ElementAt(i); // Aliases that have completed this subsequent prerequisite var subquery = stepService.Queryable().AsNoTracking() .Where(s => s.StepStatus.IsCompleteStatus && s.StepTypeId == stepTypeId) .Select(s => s.PersonAlias.PersonId); // Find the intersection (people in the main query who have also met this prerequisite) query = query.Intersect(subquery); } return(query); }
/// <summary> /// Gets the expression. /// </summary> /// <param name="entityType"></param> /// <param name="serviceInstance">The service instance.</param> /// <param name="parameterExpression">The parameter expression.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override Expression GetExpression(Type entityType, IService serviceInstance, ParameterExpression parameterExpression, string selection) { if (string.IsNullOrWhiteSpace(selection)) { return(null); } var values = JsonConvert.DeserializeObject <List <string> >(selection); if (values.Count < 3) { return(null); } var stepProgramGuid = values[0].AsGuid(); var stepTypeGuid = values[1].AsGuid(); var selectedProperty = values[2]; var stepProgram = GetStepProgram(stepProgramGuid); if (stepProgram == null) { return(null); } var stepType = GetStepType(stepTypeGuid); if (stepType == null) { return(null); } var rockContext = ( RockContext )serviceInstance.Context; var entityFields = GetStepAttributes(stepType.Id); var entityField = entityFields.FindFromFilterSelection(selectedProperty); if (entityField == null) { return(null); } // Find matchings Steps. var stepService = new StepService(rockContext); var stepParameterExpression = stepService.ParameterExpression; var attributeFilterValues = values.Skip(3).ToList(); var attributeWhereExpression = GetAttributeExpression(stepService, stepParameterExpression, entityField, attributeFilterValues); var stepQuery = stepService.Queryable() .Where(stepParameterExpression, attributeWhereExpression); // Get Person records associated with the Steps. var personService = new PersonService(rockContext); var personQuery = personService.Queryable() .Where(p => stepQuery.Any(x => x.PersonAlias.PersonId == p.Id)); // Extract the expression. var dataFilterExpression = FilterExpressionExtractor.Extract <Rock.Model.Person>(personQuery, parameterExpression, "p"); return(dataFilterExpression); }
/// <summary> /// Gets the expression. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="serviceInstance">The service instance.</param> /// <param name="parameterExpression">The parameter expression.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override Expression GetExpression(Type entityType, IService serviceInstance, ParameterExpression parameterExpression, string selection) { var settings = new FilterSettings(selection); var context = ( RockContext )serviceInstance.Context; // Get the Data View that defines the set of related records from which entities can be selected. var dataView = DataComponentSettingsHelper.GetDataViewForFilterComponent(settings.DataViewGuid, context); // Evaluate the Data View that defines the related records. var relatedEntityService = new StepService(context); var relatedEntityQuery = relatedEntityService.Queryable(); if (dataView != null) { relatedEntityQuery = DataComponentSettingsHelper.FilterByDataView(relatedEntityQuery, dataView, relatedEntityService); } // Get all of the People corresponding to the qualifying related records. var personService = new PersonService(( RockContext )serviceInstance.Context); var qry = personService.Queryable() .Where(p => relatedEntityQuery.Any(xx => xx.PersonAlias.PersonId == p.Id)); // Retrieve the Filter Expression. var extractedFilterExpression = FilterExpressionExtractor.Extract <Model.Person>(qry, parameterExpression, "p"); return(extractedFilterExpression); }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { var dataContext = new RockContext(); var stepProgramsQry = new StepProgramService(dataContext) .Queryable(); // Filter by: Category if (_categoryGuids.Any()) { stepProgramsQry = stepProgramsQry.Where(a => a.Category != null && _categoryGuids.Contains(a.Category.Guid)); } else { var categoryId = rFilter.GetUserPreference("Category").AsIntegerOrNull(); if (categoryId.HasValue && categoryId > 0) { stepProgramsQry = stepProgramsQry.Where(a => a.CategoryId == categoryId.Value); } } // Filter by: Active var activeFilter = rFilter.GetUserPreference("Active").ToLower(); switch (activeFilter) { case "active": stepProgramsQry = stepProgramsQry.Where(a => a.IsActive); break; case "inactive": stepProgramsQry = stepProgramsQry.Where(a => !a.IsActive); break; } // Sort by: Order stepProgramsQry = stepProgramsQry.OrderBy(b => b.Order); // Retrieve the Step Program data models and create corresponding view models to display in the grid. var stepService = new StepService(dataContext); var completedStepsQry = stepService.Queryable().Where(x => x.StepStatus != null && x.StepStatus.IsCompleteStatus); var stepPrograms = stepProgramsQry.Select(x => new StepProgramListItemViewModel { Id = x.Id, Name = x.Name, IconCssClass = x.IconCssClass, Category = x.Category.Name, StepTypeCount = x.StepTypes.Count, StepCompletedCount = completedStepsQry.Count(y => y.StepType.StepProgramId == x.Id) }) .ToList(); gStepProgram.DataSource = stepPrograms; gStepProgram.DataBind(); }
/// <summary> /// Delete the test data /// </summary> private static void DeleteTestData() { using (var rockContext = new RockContext()) { var stepService = new StepService(rockContext); var stepQuery = stepService.Queryable().Where(s => s.ForeignKey == ForeignKey); stepService.DeleteRange(stepQuery); rockContext.SaveChanges(); } using (var rockContext = new RockContext()) { var stepProgramService = new StepProgramService(rockContext); var stepProgramQuery = stepProgramService.Queryable().Where(sp => sp.ForeignKey == ForeignKey); stepProgramService.DeleteRange(stepProgramQuery); rockContext.SaveChanges(); } using (var rockContext = new RockContext()) { var personSearchKeyService = new PersonSearchKeyService(rockContext); var personSearchKeyQuery = personSearchKeyService.Queryable() .Where(psk => psk.PersonAlias.Person.ForeignKey == ForeignKey || PersonGuids.Contains(psk.PersonAlias.Person.Guid)); personSearchKeyService.DeleteRange(personSearchKeyQuery); rockContext.SaveChanges(); } using (var rockContext = new RockContext()) { var personAliasService = new PersonAliasService(rockContext); var personAliasQuery = personAliasService.Queryable() .Where(pa => pa.Person.ForeignKey == ForeignKey || PersonGuids.Contains(pa.Person.Guid)); personAliasService.DeleteRange(personAliasQuery); rockContext.SaveChanges(); } using (var rockContext = new RockContext()) { var personService = new PersonService(rockContext); var personQuery = personService.Queryable() .Where(p => p.ForeignKey == ForeignKey || PersonGuids.Contains(p.Guid)); personService.DeleteRange(personQuery); rockContext.SaveChanges(); } }
/// <summary> /// Gets the source entities query. This is the set of source entities that should be passed to the process method /// when processing this achievement type. /// </summary> /// <param name="achievementTypeCache">The achievement type cache.</param> /// <param name="rockContext">The rock context.</param> /// <returns></returns> /// <exception cref="NotImplementedException"></exception> public override IQueryable <IEntity> GetSourceEntitiesQuery(AchievementTypeCache achievementTypeCache, RockContext rockContext) { var stepProgram = GetStepProgramCache(achievementTypeCache); var stepTypes = stepProgram.StepTypes; var service = new StepService(rockContext); var query = service.Queryable(); if (stepTypes?.Any() == true) { var stepTypeIds = stepTypes.Select(st => st.Id); return(query.Where(s => stepTypeIds.Contains(s.StepTypeId))); } return(query); }
/// <summary> /// These are people that cannot have new step because they already /// have one and are within the minimum date range. /// </summary> /// <param name="stepTypeView">The step type view.</param> /// <param name="rockContext"></param> /// <param name="minDaysBetweenSteps"></param> /// <returns></returns> private IQueryable <int> GetPeopleThatCannotGetStepQuery(RockContext rockContext, StepTypeView stepTypeView, int minDaysBetweenSteps) { var stepService = new StepService(rockContext); var minStepDate = DateTime.MinValue; // We are querying for people that will ultimately be excluded from getting a new // step created from this job. // If duplicates are not allowed, then we want to find anyone with a step ever // If duplicates are allowed and a day range is set, then it is within that timeframe. if (stepTypeView.AllowMultiple && minDaysBetweenSteps >= 1) { minStepDate = RockDateTime.Now.AddDays(0 - minDaysBetweenSteps); } var query = stepService.Queryable().AsNoTracking() .Where(s => s.StepTypeId == stepTypeView.StepTypeId && (!s.CompletedDateTime.HasValue || s.CompletedDateTime.Value >= minStepDate)) .Select(s => s.PersonAlias.PersonId); return(query); }
/// <summary> /// These are people that cannot have new step because they already /// have one and are within the minimum date range. /// </summary> /// <param name="stepTypeView">The step type view.</param> /// <param name="rockContext"></param> /// <param name="minDaysBetweenSteps"></param> /// <returns></returns> private IQueryable <int> GetPersonIdsThatCannotGetStepQuery(RockContext rockContext, StepTypeView stepTypeView, int minDaysBetweenSteps) { // We are querying for people that will ultimately be excluded from getting a new // step created from this job. var stepService = new StepService(rockContext); var query = stepService.Queryable().AsNoTracking().Where(s => s.StepTypeId == stepTypeView.StepTypeId); if (stepTypeView.AllowMultiple) { // If allow multiple and completed date is within the minDaysBetweenSteps timeframe var minStepDate = minDaysBetweenSteps >= 1 ? RockDateTime.Now.AddDays(0 - minDaysBetweenSteps) : DateTime.MinValue; query = query.Where(s => s.CompletedDateTime.HasValue && s.CompletedDateTime >= minStepDate); } else { // If not allow multiple and has a completed date at all query = query.Where(s => s.CompletedDateTime.HasValue); } return(query.Select(s => s.PersonAlias.PersonId)); }
/// <summary> /// Gets the expression. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="serviceInstance">The service instance.</param> /// <param name="parameterExpression">The parameter expression.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override Expression GetExpression(Type entityType, IService serviceInstance, ParameterExpression parameterExpression, string selection) { var settings = new FilterSettings(selection); if (!settings.IsValid) { return(null); } var dataContext = ( RockContext )serviceInstance.Context; int stepProgramId = 0; var stepProgram = GetStepProgram(dataContext, settings.StepProgramGuid); if (stepProgram != null) { stepProgramId = stepProgram.Id; } var stepService = new StepService(dataContext); // Filter by Step Program var stepQuery = stepService.Queryable().Where(x => x.StepType.StepProgramId == stepProgramId); // Filter by Step Types if (settings.StepTypeGuids.Count() > 0) { var stepTypeService = new StepTypeService(dataContext); var stepTypeIds = stepTypeService.Queryable() .Where(a => settings.StepTypeGuids.Contains(a.Guid)) .Select(a => a.Id).ToList(); stepQuery = stepQuery.Where(x => stepTypeIds.Contains(x.StepTypeId)); } // Filter by Step Status if (settings.StepStatusGuids.Count() > 0) { var stepStatusService = new StepStatusService(dataContext); var stepStatusIds = stepStatusService.Queryable() .Where(a => settings.StepStatusGuids.Contains(a.Guid)) .Select(a => a.Id).ToList(); stepQuery = stepQuery.Where(x => x.StepStatusId.HasValue && stepStatusIds.Contains(x.StepStatusId.Value)); } // Filter by Date Started if (settings.StartedInPeriod != null) { var startDateRange = settings.StartedInPeriod.GetDateRange(TimePeriodDateRangeBoundarySpecifier.Exclusive); if (startDateRange.Start != null) { stepQuery = stepQuery.Where(x => x.StartDateTime > startDateRange.Start.Value); } if (startDateRange.End != null) { stepQuery = stepQuery.Where(x => x.StartDateTime < startDateRange.End.Value); } } // Filter by Date Completed if (settings.CompletedInPeriod != null) { var completedDateRange = settings.CompletedInPeriod.GetDateRange(TimePeriodDateRangeBoundarySpecifier.Exclusive); if (completedDateRange.Start != null) { stepQuery = stepQuery.Where(x => x.CompletedDateTime > completedDateRange.Start.Value); } if (completedDateRange.End != null) { stepQuery = stepQuery.Where(x => x.CompletedDateTime < completedDateRange.End.Value); } } // Filter by Step Campus if (settings.StepCampusGuids.Count() > 0) { var campusService = new CampusService(dataContext); var stepCampusIds = campusService.Queryable() .Where(a => settings.StepCampusGuids.Contains(a.Guid)) .Select(a => a.Id).ToList(); stepQuery = stepQuery.Where(x => x.CampusId.HasValue && stepCampusIds.Contains(x.CampusId.Value)); } // Create Person Query. var personService = new PersonService(( RockContext )serviceInstance.Context); var qry = personService.Queryable() .Where(p => stepQuery.Any(x => x.PersonAlias.PersonId == p.Id)); var extractedFilterExpression = FilterExpressionExtractor.Extract <Rock.Model.Person>(qry, parameterExpression, "p"); return(extractedFilterExpression); }
/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> /// <exception cref="System.NotImplementedException"></exception> public void Execute(IJobExecutionContext context) { JobDataMap dataMap = context.JobDetail.JobDataMap; // get the configured timeout, or default to 60 minutes if it is blank var commandTimeout = dataMap.GetString(AttributeKey.CommandTimeout).AsIntegerOrNull() ?? AttributeDefaults.CommandTimeout; var isProcessingComplete = false; var batchSize = 2; var totalBatchSize = 0; var currentBatch = 1; totalBatchSize = new StepService(new RockContext()) .Queryable() .Where(a => a.CompletedDateTime.HasValue && !a.StepProgramCompletionId.HasValue) .Select(a => a.PersonAlias.PersonId) .Distinct() .Count(); var runtime = System.Diagnostics.Stopwatch.StartNew(); var lastProcessedPersonId = 0; while (!isProcessingComplete) { using (var rockContext = new RockContext()) { var stepTypeService = new StepTypeService(rockContext); var stepService = new StepService(rockContext); var personQry = stepService .Queryable() .Where(a => a.CompletedDateTime.HasValue && !a.StepProgramCompletionId.HasValue && a.PersonAlias.PersonId > lastProcessedPersonId) .Select(a => a.PersonAlias.PersonId) .Distinct() .OrderBy(a => a) .Take(batchSize); var stepProgramStepTypeMappings = stepTypeService .Queryable() .Where(a => a.IsActive) .GroupBy(a => a.StepProgramId) .ToDictionary(a => a.Key, b => b.Select(c => c.Id).ToList()); var steps = new StepService(rockContext) .Queryable("PersonAlias") .AsNoTracking() .Where(a => personQry.Contains(a.PersonAlias.PersonId) && !a.StepProgramCompletionId.HasValue && a.CompletedDateTime.HasValue) .ToList(); isProcessingComplete = personQry.Count() < batchSize; var batchPersonIds = personQry.ToList(); foreach (var personId in batchPersonIds) { var personSteps = steps.Where(a => a.PersonAlias.PersonId == personId); if (!personSteps.Any()) { continue; } foreach (var stepProgramId in stepProgramStepTypeMappings.Keys) { var stepTypeIds = stepProgramStepTypeMappings[stepProgramId]; var stepsByProgram = personSteps.Where(a => stepTypeIds.Contains(a.StepTypeId)).OrderBy(a => a.CompletedDateTime).ToList(); if (!stepsByProgram.Any()) { continue; } while (stepsByProgram.Any() && stepTypeIds.All(a => stepsByProgram.Any(b => b.StepTypeId == a))) { var stepSet = new List <Step>(); foreach (var stepTypeId in stepTypeIds) { var step = stepsByProgram.Where(a => a.StepTypeId == stepTypeId).FirstOrDefault(); if (step == null) { continue; } stepSet.Add(step); stepsByProgram.RemoveAll(a => a.Id == step.Id); } var personAliasId = stepSet.Select(a => a.PersonAliasId).FirstOrDefault(); StepService.UpdateStepProgramCompletion(stepSet, personAliasId, stepProgramId); } } lastProcessedPersonId = personId; } var processTime = runtime.ElapsedMilliseconds; var recordsProcessed = ( double )(batchSize * currentBatch) + batchPersonIds.Count; var recordsPerMillisecond = recordsProcessed / processTime; var recordsRemaining = totalBatchSize - recordsProcessed; var minutesRemaining = recordsRemaining / recordsPerMillisecond / 1000 / 60; context.UpdateLastStatusMessage($"Processing {recordsProcessed} of {totalBatchSize} records. Approximately {minutesRemaining:N0} minutes remaining."); currentBatch++; } } ServiceJobService.DeleteJob(context.GetJobId()); }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { if (!_blockContextIsValid) { return; } if (_program == null) { return; } var dataContext = this.GetDataContext(); var stepTypesQry = new StepTypeService(dataContext) .Queryable(); // Filter by: Step Programs stepTypesQry = stepTypesQry.Where(x => x.StepProgramId == _program.Id); // Filter by: Name var name = rFilter.GetUserPreference(FilterSettingName.Name).ToStringSafe(); if (!string.IsNullOrWhiteSpace(name)) { stepTypesQry = stepTypesQry.Where(a => a.Name.Contains(name)); } // Filter by: Allow Multiple var allowMultiple = rFilter.GetUserPreference(FilterSettingName.AllowMultiple).AsBooleanOrNull(); if (allowMultiple.HasValue) { stepTypesQry = stepTypesQry.Where(a => a.AllowMultiple == allowMultiple.Value); } // Filter by: Has Duration var hasDuration = rFilter.GetUserPreference(FilterSettingName.SpansTime).AsBooleanOrNull(); if (hasDuration.HasValue) { stepTypesQry = stepTypesQry.Where(a => a.HasEndDate == hasDuration.Value); } // Filter by: Active var activeFilter = rFilter.GetUserPreference(FilterSettingName.ActiveStatus).ToUpperInvariant(); switch (activeFilter) { case "ACTIVE": stepTypesQry = stepTypesQry.Where(a => a.IsActive); break; case "INACTIVE": stepTypesQry = stepTypesQry.Where(a => !a.IsActive); break; } // Sort by: Order, Id. stepTypesQry = stepTypesQry.OrderBy(b => b.Order).ThenBy(b => b.Id); // Retrieve the Step Type data models and create corresponding view models to display in the grid. var stepService = new StepService(dataContext); var startedStepsQry = stepService.Queryable(); var completedStepsQry = stepService.Queryable().Where(x => x.StepStatus != null && x.StepStatus.IsCompleteStatus); var stepTypes = stepTypesQry.Select(x => new StepTypeListItemViewModel { Id = x.Id, Name = x.Name, IconCssClass = x.IconCssClass, AllowMultipleInstances = x.AllowMultiple, HasDuration = x.HasEndDate, StartedCount = startedStepsQry.Count(y => y.StepTypeId == x.Id), CompletedCount = completedStepsQry.Count(y => y.StepTypeId == x.Id) }) .ToList(); gStepType.DataSource = stepTypes; gStepType.DataBind(); }
/// <summary> /// Processes the step type. Add steps for everyone in the dataview /// </summary> /// <param name="jobContext">The job context.</param> /// <param name="stepTypeView">The step type view.</param> /// <param name="minDaysBetweenSteps">The minimum days between steps.</param> /// <param name="addedResults">The added results.</param> /// <param name="updatedResults">The updated results.</param> /// <param name="errorMessages">The error message.</param> private void ProcessStepType( IJobExecutionContext jobContext, StepTypeView stepTypeView, int minDaysBetweenSteps, ConcurrentBag <int> addedResults, ConcurrentBag <int> updatedResults, out List <string> errorMessages) { errorMessages = new List <string>(); var rockContextGetList = new RockContext(); rockContextGetList.Database.CommandTimeout = SqlCommandTimeoutSeconds; // Steps are created with a status of "complete", so if we need to know the status id var stepStatusId = stepTypeView.CompletedStepStatusIds.FirstOrDefault(); if (stepStatusId == default) { errorMessages.Add($"The Step Type with id {stepTypeView.StepTypeId} does not have a valid Complete Status to use"); return; } // Get the dataview configured for the step type var dataViewService = new DataViewService(rockContextGetList); var dataview = dataViewService.Get(stepTypeView.AutoCompleteDataViewId); if (dataview == null) { errorMessages.Add($"The dataview {stepTypeView.AutoCompleteDataViewId} for step type {stepTypeView.StepTypeId} did not resolve"); return; } // We can use the dataview to get the person alias id query var dataViewGetQueryArgs = new DataViewGetQueryArgs { DbContext = rockContextGetList, DatabaseTimeoutSeconds = SqlCommandTimeoutSeconds }; IQueryable <IEntity> dataviewQuery; try { dataviewQuery = dataview.GetQuery(dataViewGetQueryArgs); } catch (Exception ex) { errorMessages.Add(ex.Message); ExceptionLogService.LogException(ex); return; } if (dataviewQuery == null) { errorMessages.Add($"Generating a query for dataview {stepTypeView.AutoCompleteDataViewId} for step type {stepTypeView.StepTypeId} was not successful"); return; } // This query contains person ids in the dataview var personIdQuery = dataviewQuery.AsNoTracking().Select(e => e.Id); // Get the query for people that cannot get a new step var personIdsThatCannotGetStepQuery = GetPersonIdsThatCannotGetStepQuery(rockContextGetList, stepTypeView, minDaysBetweenSteps); // Subtract the people that cannot get a new step personIdQuery = personIdQuery.Except(personIdsThatCannotGetStepQuery); // If there are prerequisites, then subtract the people that cannot get the step because of unmet prerequisites if (stepTypeView.PrerequisiteStepTypeIds.Any()) { var personIdsThatHaveMetPrerequisitesQuery = GetPersonIdsThatHaveMetPrerequisitesQuery(rockContextGetList, stepTypeView); personIdQuery = personIdQuery.Intersect(personIdsThatHaveMetPrerequisitesQuery); } // Convert to person aliases ids var personAliasService = new PersonAliasService(rockContextGetList); var personInfoList = personAliasService.GetPrimaryAliasQuery() .Where(a => personIdQuery.Contains(a.PersonId)) .Select(a => new { PersonId = a.PersonId, PrimaryAliasId = a.Id }) .ToList(); // Add or update steps for each of the remaining aliases that have met all the conditions var stepServiceGetList = new StepService(rockContextGetList); var now = RockDateTime.Now; var addedCount = 0; var updatedCount = 0; // Query for existing incomplete steps for the people var existingIncompleteStepIdsByPersonId = stepServiceGetList.Queryable() .Where(s => s.StepTypeId == stepTypeView.StepTypeId && personIdQuery.Contains(s.PersonAlias.PersonId) && !s.CompletedDateTime.HasValue) .Select(a => new { a.PersonAlias.PersonId, StepId = a.Id }) .ToList() .GroupBy(a => a.PersonId) .ToDictionary( k => k.Key, // just in case the Person is has more than one incomplete step for this step type, just use the latest one // it should clean it self up on subsequent runs since the other steps for this person wouldn't have been marked complete yet v => v.Max(s => s.StepId) ); long totalCount = personInfoList.Count; long progressCount = 0; foreach (var personIdInfo in personInfoList) { var personId = personIdInfo.PersonId; var personPrimaryAliasId = personIdInfo.PrimaryAliasId; var existingStepId = existingIncompleteStepIdsByPersonId.GetValueOrNull(personId); using (var rockContextLoop = new RockContext()) { var stepServiceLoop = new StepService(rockContextLoop); Step step; if (existingStepId.HasValue) { step = stepServiceLoop.Get(existingStepId.Value); } else { step = new Step { StepTypeId = stepTypeView.StepTypeId, Caption = stepTypeView.Name, StartDateTime = now, PersonAliasId = personPrimaryAliasId }; } step.CompletedDateTime = now; step.StepStatusId = stepStatusId; if (!existingStepId.HasValue) { stepServiceLoop.AddWithoutValidation(step); addedCount++; } else { updatedCount++; } rockContextLoop.SaveChanges(); } progressCount++; // Update the progress every 5 seconds if ((RockDateTime.Now - _lastProgressUpdate).TotalSeconds >= 5) { try { jobContext.UpdateLastStatusMessage($"Processing {stepTypeView.Name } steps : {progressCount}/{totalCount}"); } catch (Exception ex) { // ignore, but write to debug output System.Diagnostics.Debug.WriteLine($"Error updating LastStatusMessage for ProcessStepType loop: {ex}"); } finally { _lastProgressUpdate = RockDateTime.Now; } } } addedResults.Add(addedCount); updatedResults.Add(updatedCount); }
/// <summary> /// Render the grid view's grid /// </summary> private void RenderStepGrid() { if (!ValidateRequiredModels()) { return; } // Get the initial query var stepTypes = GetStepTypes(); // Get filter values var stepTypeNameFilter = gfGridFilter.GetUserPreference(FilterKey.StepTypeName); var stepStatusNameFilter = gfGridFilter.GetUserPreference(FilterKey.StepStatusName); // Apply step type filters if (!string.IsNullOrEmpty(stepTypeNameFilter)) { stepTypes = stepTypes.Where(st => st.Name.Contains(stepTypeNameFilter)).ToList(); } // Get the step type Ids var stepTypeIds = stepTypes.Select(st => st.Id).ToList(); // Query for the steps var rockContext = GetRockContext(); var stepService = new StepService(rockContext); var person = GetPerson(); var stepsQuery = stepService.Queryable() .AsNoTracking() .Include(s => s.StepType) .Include(s => s.StepStatus) .Where(s => s.PersonAlias.PersonId == person.Id && stepTypeIds.Contains(s.StepTypeId)); // Apply step filters if (!string.IsNullOrEmpty(stepStatusNameFilter)) { stepsQuery = stepsQuery.Where(s => s.StepStatus != null && s.StepStatus.Name.Contains(stepStatusNameFilter)); } // Create a view model for each step var viewModels = stepsQuery.Select(s => new StepGridRowViewModel { Id = s.Id, StepTypeName = s.StepType.Name, CompletedDateTime = s.CompletedDateTime, StepStatusColor = s.StepStatus == null ? string.Empty : s.StepStatus.StatusColor, StepStatusName = s.StepStatus == null ? string.Empty : s.StepStatus.Name, StepTypeIconCssClass = s.StepType.IconCssClass, StepTypeOrder = s.StepType.Order, Summary = string.Empty // TODO }); // Sort the view models if (gStepList.SortProperty != null) { viewModels = viewModels.Sort(gStepList.SortProperty); } else { viewModels = viewModels.OrderBy(vm => vm.StepTypeOrder).ThenBy(vm => vm.StepTypeName); } // Bind the grid for the steps gStepList.SetLinqDataSource(viewModels); gStepList.DataBind(); }
/// <summary> /// Migrates a baptism record from a Attribute Matrix Item to a Step /// </summary> /// <param name="itemId">Matrix Item Id</param> /// <param name="personId">The Person Id of the person who was baptized.</param> /// <returns></returns> private bool MigrateBaptismItem(int itemId, int personId) { using (var context = new RockContext()) { var matrixItem = new AttributeMatrixItemService(context).Get(itemId); var person = new PersonService(context).Get(personId); if (matrixItem == null) { results["Fail"] += String.Format("Failed Migration {0} - {1}, baptism matrix item not found.", itemId, person != null ? person.FullName : "Unknown") + Environment.NewLine; return(false); } matrixItem.LoadAttributes(context); var campusGuid = matrixItem.GetAttributeValue("BaptismLocation").AsGuidOrNull(); var baptismDate = matrixItem.GetAttributeValue("BaptismDate").AsDateTime(); var baptizedBy = matrixItem.GetAttributeValue("BaptizedBy"); var baptismTypeGuid = matrixItem.GetAttributeValue("BaptismType").AsGuidOrNull(); var stepService = new StepService(context); var step = stepService.Queryable() .Where(s => s.ForeignId == itemId) .Where(s => s.PersonAlias.PersonId == personId) .SingleOrDefault(); if (step == null) { step = new Step() { StepTypeId = BaptismStepType.Id, PersonAliasId = person.PrimaryAliasId.Value, ForeignId = matrixItem.Id }; stepService.Add(step); } if (baptismDate >= new DateTime(1753, 1, 1)) //datetime minimum date { step.StartDateTime = baptismDate; step.CompletedDateTime = baptismDate; } step.StepStatusId = StepStatus.Id; if (campusGuid.HasValue) { step.CampusId = CampusCache.Get(campusGuid.Value).Id; } context.SaveChanges(); step.LoadAttributes(context); step.SetAttributeValue("BaptismType", baptismTypeGuid); if (baptizedBy.IsNotNullOrWhiteSpace()) { step.SetAttributeValue("BaptizedBy", baptizedBy); } else { step.SetAttributeValue("BaptizedBy", null); } step.SaveAttributeValues(context); results["Success"] += String.Format("Successfully migrated baptism item {0}-{1} for {2}.", matrixItem.Id, baptismTypeGuid.HasValue ? DefinedValueCache.Get(baptismTypeGuid.Value).Value : "Unknown Type", person != null ? person.FullName : "Unknown") + Environment.NewLine; return(true); } }
/// <summary> /// Binds the group members grid. /// </summary> protected void BindParticipantsGrid(bool isExporting = false, bool isCommunication = false) { if (_stepType == null) { pnlSteps.Visible = false; return; } pnlSteps.Visible = true; rFilter.Visible = true; gSteps.Visible = true; var campusCount = CampusCache.All(false).Count; if (campusCount <= 1) { var campusColumn = gSteps.ColumnsOfType <RockBoundField>().Where(a => a.DataField == "CampusName").FirstOrDefault(); if (campusColumn != null) { campusColumn.Visible = false; } } lHeading.Text = string.Format("{0} Steps", _stepType.Name); _fullNameField = gSteps.ColumnsOfType <RockLiteralField>().Where(a => a.ID == "lExportFullName").FirstOrDefault(); _nameWithHtmlField = gSteps.ColumnsOfType <RockLiteralField>().Where(a => a.ID == "lNameWithHtml").FirstOrDefault(); var dataContext = GetDataContext(); var stepService = new StepService(dataContext); var qry = stepService.Queryable() .Include(x => x.StepStatus) .Include(x => x.PersonAlias.Person) .AsNoTracking() .Where(x => x.StepTypeId == _stepType.Id); // Filter by First Name string firstName = tbFirstName.Text; if (!string.IsNullOrWhiteSpace(firstName)) { qry = qry.Where(m => m.PersonAlias.Person.FirstName.StartsWith(firstName) || m.PersonAlias.Person.NickName.StartsWith(firstName)); } // Filter by Last Name string lastName = tbLastName.Text; if (!string.IsNullOrWhiteSpace(lastName)) { qry = qry.Where(m => m.PersonAlias.Person.LastName.StartsWith(lastName)); } // Filter by Step Status var validStatusIds = _stepType.StepProgram.StepStatuses.Select(r => r.Id).ToList(); var statusIds = new List <int>(); foreach (var statusId in cblStepStatus.SelectedValues.AsIntegerList()) { if (validStatusIds.Contains(statusId)) { statusIds.Add(statusId); } } if (statusIds.Any()) { qry = qry.Where(m => statusIds.Contains(m.StepStatusId ?? 0)); } // Filter By Start Date var startDateRange = DateRangePicker.CalculateDateRangeFromDelimitedValues(drpDateStarted.DelimitedValues); if (startDateRange.Start.HasValue) { qry = qry.Where(m => m.StartDateTime.HasValue && m.StartDateTime.Value >= startDateRange.Start.Value); } if (startDateRange.End.HasValue) { var exclusiveEndDate = startDateRange.End.Value.Date.AddDays(1); qry = qry.Where(m => m.StartDateTime.HasValue && m.StartDateTime.Value < exclusiveEndDate); } // Filter by Date Completed var completedDateRange = DateRangePicker.CalculateDateRangeFromDelimitedValues(drpDateCompleted.DelimitedValues); if (completedDateRange.Start.HasValue) { qry = qry.Where(m => m.CompletedDateTime.HasValue && m.CompletedDateTime.Value >= completedDateRange.Start.Value); } if (completedDateRange.End.HasValue) { var exclusiveEndDate = completedDateRange.End.Value.Date.AddDays(1); qry = qry.Where(m => m.CompletedDateTime.HasValue && m.CompletedDateTime.Value < exclusiveEndDate); } // Filter by Note string note = tbNote.Text; if (!string.IsNullOrWhiteSpace(note)) { qry = qry.Where(m => m.Note.Contains(note)); } var campusId = cpCampusFilter.SelectedCampusId; if (campusId != null) { qry = qry.Where(m => m.CampusId == campusId); } // Filter query by any configured attribute filters if (AvailableAttributes != null && AvailableAttributes.Any()) { foreach (var attribute in AvailableAttributes) { var filterControl = phAttributeFilters.FindControl("filter_" + attribute.Id.ToString()); qry = attribute.FieldType.Field.ApplyAttributeQueryFilter(qry, filterControl, attribute, stepService, Rock.Reporting.FilterMode.SimpleFilter); } } // Apply Grid Sort var sortProperty = gSteps.SortProperty; if (sortProperty != null) { qry = qry.Sort(sortProperty); } else { qry = qry.OrderBy(a => a.PersonAlias.Person.LastName).ThenBy(a => a.PersonAlias.Person.FirstName); } var stepIdQuery = qry.Select(m => m.Id); _inactiveStatus = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_INACTIVE); gSteps.EntityTypeId = new Step().TypeId; _stepStatusField = gSteps.ColumnsOfType <RockLiteralField>().FirstOrDefault(a => a.ID == lStepStatusHtml.ID); _stepDateStartedField = gSteps.ColumnsOfType <RockBoundField>().FirstOrDefault(a => a.HeaderText == "Date Started"); if (_stepDateStartedField != null) { _stepDateStartedField.Visible = _stepType.HasEndDate; } _showNoteColumn = GetAttributeValue(AttributeKey.ShowNoteColumn).AsBoolean(); gSteps.ColumnsOfType <RockBoundField>().First(a => a.DataField == "Note").Visible = _showNoteColumn; var hasDuration = _stepType.HasEndDate; var qrySteps = qry.Select(x => new StepParticipantListViewModel { Id = x.Id, PersonId = x.PersonAlias.PersonId, LastName = x.PersonAlias.Person.LastName, NickName = x.PersonAlias.Person.NickName, StartedDateTime = x.StartDateTime, CompletedDateTime = x.CompletedDateTime, StepStatusName = (x.StepStatus == null ? "" : x.StepStatus.Name), IsCompleted = (x.StepStatus == null ? false : x.StepStatus.IsCompleteStatus), Note = x.Note, CampusName = x.Campus == null ? string.Empty : x.Campus.Name, Person = x.PersonAlias.Person }); // Add the Step data models to the grid object list to allow custom attribute values to be read. if (this.AvailableAttributes != null && this.AvailableAttributes.Any()) { gSteps.ObjectList = qry.ToDictionary(k => k.Id.ToString(), v => ( object )v); } gSteps.SetLinqDataSource(qrySteps); gSteps.DataBind(); }
public void StepDateKeyJoinsCorrectly() { var expectedRecordCount = 15; var startYear = 2015; var completedYear = 2016; var endYear = 2017; using (var rockContext = new RockContext()) { var stepService = new StepService(rockContext); var minStartDateValue = TestDataHelper.GetAnalyticsSourceMinDateForYear(rockContext, startYear); var maxStartDateValue = TestDataHelper.GetAnalyticsSourceMaxDateForYear(rockContext, startYear); var minCompletedDateValue = TestDataHelper.GetAnalyticsSourceMinDateForYear(rockContext, completedYear); var maxCompletedDateValue = TestDataHelper.GetAnalyticsSourceMaxDateForYear(rockContext, completedYear); var minEndDateValue = TestDataHelper.GetAnalyticsSourceMinDateForYear(rockContext, endYear); var maxEndDateValue = TestDataHelper.GetAnalyticsSourceMaxDateForYear(rockContext, endYear); for (var i = 0; i < 15; i++) { var startDate = TestDataHelper.GetRandomDateInRange(minStartDateValue, maxStartDateValue); var endDate = TestDataHelper.GetRandomDateInRange(minEndDateValue, maxEndDateValue); var completedDate = TestDataHelper.GetRandomDateInRange(minCompletedDateValue, maxCompletedDateValue); while (endDate < startDate) { endDate = TestDataHelper.GetRandomDateInRange(minEndDateValue, maxEndDateValue); } while (completedDate < startDate) { completedDate = TestDataHelper.GetRandomDateInRange(minCompletedDateValue, maxCompletedDateValue); } var step = BuildStep(rockContext, completedDate, startDate, endDate); stepService.Add(step); } rockContext.SaveChanges(); } using (var rockContext = new RockContext()) { var stepService = new StepService(rockContext); var steps = stepService. Queryable(). Where(i => i.ForeignKey == stepForiegnKey). Where(i => i.CompletedSourceDate.CalendarYear == completedYear); Assert.AreEqual(expectedRecordCount, steps.Count()); Assert.IsNotNull(steps.First().CompletedSourceDate); steps = stepService. Queryable(). Where(i => i.ForeignKey == stepForiegnKey). Where(i => i.StartSourceDate.CalendarYear == startYear); Assert.AreEqual(expectedRecordCount, steps.Count()); Assert.IsNotNull(steps.First().StartSourceDate); steps = stepService. Queryable(). Where(i => i.ForeignKey == stepForiegnKey). Where(i => i.EndSourceDate.CalendarYear == endYear); Assert.AreEqual(expectedRecordCount, steps.Count()); Assert.IsNotNull(steps.First().EndSourceDate); } }