Пример #1
0
        protected void bbAdd_OnClick(object sender, EventArgs e)
        {
            int?metricId      = hfMetricId.ValueAsInt();
            var dateTimeArray = ddlInstanceTwo.SelectedValue.Split(',');
            var dateTime      = dateTimeArray[0].AsDateTime();
            var value         = nbValue.Text.AsIntegerOrNull();

            if (metricId == 0 || !dateTime.HasValue || !value.HasValue)
            {
                nbWarning.Text    = "Unable to save. Please check you have selected an instance and input a value. Also ask your administrator to double check your Headcount Metric Sync Groups job is running.";
                nbWarning.Visible = true;
                return;
            }

            var rockContext         = new RockContext();
            var metricValueService  = new MetricValueService(rockContext);
            var existingMetricValue = metricValueService.Queryable().FirstOrDefault(v => v.MetricValueDateTime.HasValue && v.MetricValueDateTime.Value == dateTime.Value && v.MetricId == metricId);

            if (existingMetricValue != null && !string.IsNullOrWhiteSpace(existingMetricValue.MetricValuePartitionEntityIds) && existingMetricValue.MetricValuePartitionEntityIds.Split(',').Any(partition => partition.Split('|')[0].AsInteger() == EntityTypeCache.Get(typeof(Campus)).Id&& partition.Split('|')[1].AsInteger() == ddlCampuses.SelectedValueAsId()))
            {
                nbWarning.Text =
                    String.Format(
                        "A metric value already existed for the {0}, the old value of {1} has been changed to {2}",
                        dateTime.Value, Decimal.ToInt32(existingMetricValue.YValue.Value), value);
                nbWarning.Visible          = true;
                existingMetricValue.YValue = value;
            }
            else
            {
                var metric      = new MetricService(rockContext).Get(metricId.Value);
                var metricValue = new MetricValue();
                metricValue.MetricValueDateTime = dateTime;
                metricValue.YValue = value;
                metricValue.MetricValuePartitions = new List <MetricValuePartition>();
                var metricPartitionsByPosition = metric.MetricPartitions.OrderBy(a => a.Order).ToList();
                foreach (var metricPartition in metricPartitionsByPosition)
                {
                    var metricValuePartition = new MetricValuePartition();
                    metricValuePartition.MetricPartition   = metricPartition;
                    metricValuePartition.MetricPartitionId = metricPartition.Id;
                    metricValuePartition.MetricValue       = metricValue;
                    metricValuePartition.EntityId          = ddlCampuses.SelectedValueAsId();
                    metricValue.MetricValuePartitions.Add(metricValuePartition);
                }
                metricValue.MetricId = metricId.Value;
                metricValue.Note     = "Input as a headcount metric value";

                metricValueService.Add(metricValue);
                nbWarning.Text    = "";
                nbWarning.Visible = false;
            }

            nbValue.Text = "";
            rockContext.SaveChanges();
            BindGrid();
        }
Пример #2
0
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            MetricValue        metricValue;
            var                rockContext        = new RockContext();
            MetricValueService metricValueService = new MetricValueService(rockContext);

            int metricValueId = int.Parse(hfMetricValueId.Value);

            if (metricValueId == 0)
            {
                metricValue = new MetricValue();
                metricValueService.Add(metricValue);
                metricValue.MetricId = hfMetricId.ValueAsInt();
                metricValue.Metric   = metricValue.Metric ?? new MetricService(rockContext).Get(metricValue.MetricId);
                metricValue.MetricValuePartitions = new List <MetricValuePartition>();
            }
            else
            {
                metricValue = metricValueService.Get(metricValueId);
            }

            metricValue.MetricValueType     = ddlMetricValueType.SelectedValueAsEnum <MetricValueType>();
            metricValue.XValue              = tbXValue.Text;
            metricValue.YValue              = tbYValue.Text.AsDecimalOrNull();
            metricValue.Note                = tbNote.Text;
            metricValue.MetricValueDateTime = dpMetricValueDateTime.SelectedDate;

            // Get EntityId from EntityType UI controls
            foreach (var metricPartition in metricValue.Metric.MetricPartitions)
            {
                var     metricPartitionEntityType = EntityTypeCache.Get(metricPartition.EntityTypeId ?? 0);
                var     controlId             = string.Format("metricPartition{0}_entityTypeEditControl", metricPartition.Id);
                Control entityTypeEditControl = phMetricValuePartitions.FindControl(controlId);
                var     metricValuePartition  = metricValue.MetricValuePartitions.FirstOrDefault(a => a.MetricPartitionId == metricPartition.Id);
                if (metricValuePartition == null)
                {
                    metricValuePartition = new MetricValuePartition();
                    metricValuePartition.MetricPartitionId = metricPartition.Id;
                    metricValue.MetricValuePartitions.Add(metricValuePartition);
                }

                if (metricPartitionEntityType != null && metricPartitionEntityType.SingleValueFieldType != null && metricPartitionEntityType.SingleValueFieldType.Field is IEntityFieldType)
                {
                    metricValuePartition.EntityId = (metricPartitionEntityType.SingleValueFieldType.Field as IEntityFieldType).GetEditValueAsEntityId(entityTypeEditControl, new Dictionary <string, ConfigurationValue>());
                }
                else
                {
                    metricValuePartition.EntityId = null;
                }

                if (metricPartition.IsRequired && metricPartitionEntityType != null && !metricValuePartition.EntityId.HasValue)
                {
                    nbValueRequired.Text        = string.Format("A value for {0} is required", metricPartition.Label ?? metricPartitionEntityType.FriendlyName);
                    nbValueRequired.Dismissable = true;
                    nbValueRequired.Visible     = true;
                    return;
                }
            }


            if (!metricValue.IsValid)
            {
                // Controls will render the error messages
                return;
            }

            rockContext.SaveChanges();

            var qryParams = new Dictionary <string, string>();

            qryParams.Add("MetricId", hfMetricId.Value);
            qryParams.Add("MetricCategoryId", hfMetricCategoryId.Value);
            qryParams.Add("ExpandedIds", PageParameter("ExpandedIds"));
            NavigateToParentPage(qryParams);
        }
Пример #3
0
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click( object sender, EventArgs e )
        {
            MetricValue metricValue;
            var rockContext = new RockContext();
            MetricValueService metricValueService = new MetricValueService( rockContext );

            int metricValueId = int.Parse( hfMetricValueId.Value );

            if ( metricValueId == 0 )
            {
                metricValue = new MetricValue();
                metricValueService.Add( metricValue );
                metricValue.MetricId = hfMetricId.ValueAsInt();
                metricValue.Metric = metricValue.Metric ?? new MetricService( rockContext ).Get( metricValue.MetricId );
                metricValue.MetricValuePartitions = new List<MetricValuePartition>();
            }
            else
            {
                metricValue = metricValueService.Get( metricValueId );
            }

            metricValue.MetricValueType = ddlMetricValueType.SelectedValueAsEnum<MetricValueType>();
            metricValue.XValue = tbXValue.Text;
            metricValue.YValue = tbYValue.Text.AsDecimalOrNull();
            metricValue.Note = tbNote.Text;
            metricValue.MetricValueDateTime = dpMetricValueDateTime.SelectedDate;

            // Get EntityId from EntityType UI controls
            foreach ( var metricPartition in metricValue.Metric.MetricPartitions )
            {
                var metricPartitionEntityType = EntityTypeCache.Read( metricPartition.EntityTypeId ?? 0 );
                var controlId = string.Format( "metricPartition{0}_entityTypeEditControl", metricPartition.Id );
                Control entityTypeEditControl = phMetricValuePartitions.FindControl( controlId );
                var metricValuePartition = metricValue.MetricValuePartitions.FirstOrDefault( a => a.MetricPartitionId == metricPartition.Id );
                if ( metricValuePartition == null )
                {
                    metricValuePartition = new MetricValuePartition();
                    metricValuePartition.MetricPartitionId = metricPartition.Id;
                    metricValue.MetricValuePartitions.Add( metricValuePartition );
                }

                if ( metricPartitionEntityType != null && metricPartitionEntityType.SingleValueFieldType != null && metricPartitionEntityType.SingleValueFieldType.Field is IEntityFieldType )
                {
                    metricValuePartition.EntityId = ( metricPartitionEntityType.SingleValueFieldType.Field as IEntityFieldType ).GetEditValueAsEntityId( entityTypeEditControl, new Dictionary<string, ConfigurationValue>() );
                }
                else
                {
                    metricValuePartition.EntityId = null;
                }

                if ( metricPartition.IsRequired && metricPartitionEntityType != null && !metricValuePartition.EntityId.HasValue )
                {
                    nbValueRequired.Text = string.Format( "A value for {0} is required", metricPartition.Label ?? metricPartitionEntityType.FriendlyName );
                    nbValueRequired.Dismissable = true;
                    nbValueRequired.Visible = true;
                    return;
                }
            }

            if ( !metricValue.IsValid )
            {
                // Controls will render the error messages
                return;
            }

            rockContext.SaveChanges();

            var qryParams = new Dictionary<string, string>();
            qryParams.Add( "MetricId", hfMetricId.Value );
            qryParams.Add( "MetricCategoryId", hfMetricCategoryId.Value );
            qryParams.Add( "ExpandedIds", PageParameter( "ExpandedIds" ) );
            NavigateToParentPage( qryParams );
        }
Пример #4
0
        /// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Execute(IJobExecutionContext context)
        {
            var metricSourceValueTypeDataviewGuid = Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_DATAVIEW.AsGuid();
            var metricSourceValueTypeSqlGuid      = Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_SQL.AsGuid();

            var metricsQry = new MetricService(new RockContext()).Queryable().AsNoTracking().Where(
                a => a.ScheduleId.HasValue &&
                a.SourceValueTypeId.HasValue &&
                (a.SourceValueType.Guid == metricSourceValueTypeDataviewGuid || a.SourceValueType.Guid == metricSourceValueTypeSqlGuid));

            var metricIdList = metricsQry.OrderBy(a => a.Title).ThenBy(a => a.Subtitle).Select(a => a.Id).ToList();

            var    metricExceptions       = new List <Exception>();
            int    metricsCalculated      = 0;
            int    metricValuesCalculated = 0;
            Metric metric = null;

            foreach (var metricId in metricIdList)
            {
                try
                {
                    using (var rockContextForMetricEntity = new RockContext())
                    {
                        var metricService = new MetricService(rockContextForMetricEntity);

                        metric = metricService.Get(metricId);
                        var lastRunDateTime = metric.LastRunDateTime ?? metric.CreatedDateTime ?? metric.ModifiedDateTime;
                        if (lastRunDateTime.HasValue)
                        {
                            var currentDateTime = RockDateTime.Now;

                            // get all the schedule times that were supposed to run since that last time it was scheduled to run
                            var scheduledDateTimesToProcess = metric.Schedule.GetScheduledStartTimes(lastRunDateTime.Value, currentDateTime).Where(a => a > lastRunDateTime.Value).ToList();
                            foreach (var scheduleDateTime in scheduledDateTimesToProcess)
                            {
                                using (var rockContextForMetricValues = new RockContext())
                                {
                                    var metricPartitions                     = new MetricPartitionService(rockContextForMetricValues).Queryable().Where(a => a.MetricId == metric.Id).ToList();
                                    var metricValueService                   = new MetricValueService(rockContextForMetricValues);
                                    List <ResultValue> resultValues          = new List <ResultValue>();
                                    bool getMetricValueDateTimeFromResultSet = false;
                                    if (metric.SourceValueType.Guid == metricSourceValueTypeDataviewGuid)
                                    {
                                        // get the metric value from the DataView
                                        if (metric.DataView != null)
                                        {
                                            var errorMessages = new List <string>();
                                            var qry           = metric.DataView.GetQuery(null, null, out errorMessages);
                                            if (metricPartitions.Count > 1 || metricPartitions.First().EntityTypeId.HasValue)
                                            {
                                                throw new NotImplementedException("Partitioned Metrics using DataViews is not supported.");
                                            }
                                            else
                                            {
                                                var resultValue = new ResultValue();
                                                resultValue.Value               = Convert.ToDecimal(qry.Count());
                                                resultValue.Partitions          = new List <ResultValuePartition>();
                                                resultValue.MetricValueDateTime = scheduleDateTime;
                                                resultValues.Add(resultValue);
                                            }
                                        }
                                    }
                                    else if (metric.SourceValueType.Guid == metricSourceValueTypeSqlGuid)
                                    {
                                        //// calculate the metricValue using the results from the SQL
                                        //// assume SQL is in one of the following forms:
                                        //// -- "SELECT Count(*), Partion0EntityId, Partion1EntityId, Partion2EntityId,.. FROM ..."
                                        //// -- "SELECT Count(*), [MetricValueDateTime], Partion0EntityId, Partion1EntityId, Partion2EntityId,.. FROM ..."
                                        if (!string.IsNullOrWhiteSpace(metric.SourceSql))
                                        {
                                            string formattedSql = metric.SourceSql.ResolveMergeFields(metric.GetMergeObjects(scheduleDateTime));
                                            var    tableResult  = DbService.GetDataTable(formattedSql, System.Data.CommandType.Text, null);

                                            if (tableResult.Columns.Count >= 2 && tableResult.Columns[1].ColumnName == "MetricValueDateTime")
                                            {
                                                getMetricValueDateTimeFromResultSet = true;
                                            }

                                            foreach (var row in tableResult.Rows.OfType <System.Data.DataRow>())
                                            {
                                                var resultValue = new ResultValue();

                                                resultValue.Value = Convert.ToDecimal(row[0]);
                                                if (getMetricValueDateTimeFromResultSet)
                                                {
                                                    resultValue.MetricValueDateTime = Convert.ToDateTime(row[1]);
                                                }
                                                else
                                                {
                                                    resultValue.MetricValueDateTime = scheduleDateTime;
                                                }

                                                resultValue.Partitions = new List <ResultValuePartition>();
                                                int partitionPosition    = 0;
                                                int partitionFieldIndex  = getMetricValueDateTimeFromResultSet ? 2 : 1;
                                                int partitionColumnCount = tableResult.Columns.Count - 1;
                                                while (partitionFieldIndex <= partitionColumnCount)
                                                {
                                                    resultValue.Partitions.Add(new ResultValuePartition
                                                    {
                                                        PartitionPosition = partitionPosition,
                                                        EntityId          = row[partitionFieldIndex] as int?
                                                    });

                                                    partitionPosition++;
                                                    partitionFieldIndex++;
                                                }

                                                resultValues.Add(resultValue);
                                            }
                                        }
                                    }

                                    metric.LastRunDateTime = scheduleDateTime;
                                    metricsCalculated++;
                                    metricValuesCalculated += resultValues.Count();

                                    if (resultValues.Any())
                                    {
                                        List <MetricValue> metricValuesToAdd = new List <MetricValue>();
                                        foreach (var resultValue in resultValues)
                                        {
                                            var metricValue = new MetricValue();
                                            metricValue.MetricId            = metric.Id;
                                            metricValue.MetricValueDateTime = resultValue.MetricValueDateTime;
                                            metricValue.MetricValueType     = MetricValueType.Measure;
                                            metricValue.YValue                = resultValue.Value;
                                            metricValue.CreatedDateTime       = RockDateTime.Now;
                                            metricValue.ModifiedDateTime      = RockDateTime.Now;
                                            metricValue.MetricValuePartitions = new List <MetricValuePartition>();
                                            var metricPartitionsByPosition = metricPartitions.OrderBy(a => a.Order).ToList();

                                            if (!resultValue.Partitions.Any() && metricPartitionsByPosition.Count() == 1 && !metricPartitionsByPosition[0].EntityTypeId.HasValue)
                                            {
                                                // a metric with just the default partition (not partitioned by Entity)
                                                var metricPartition      = metricPartitionsByPosition[0];
                                                var metricValuePartition = new MetricValuePartition();
                                                metricValuePartition.MetricPartition   = metricPartition;
                                                metricValuePartition.MetricPartitionId = metricPartition.Id;
                                                metricValuePartition.MetricValue       = metricValue;
                                                metricValuePartition.EntityId          = null;
                                                metricValue.MetricValuePartitions.Add(metricValuePartition);
                                            }
                                            else
                                            {
                                                foreach (var partitionResult in resultValue.Partitions)
                                                {
                                                    if (metricPartitionsByPosition.Count > partitionResult.PartitionPosition)
                                                    {
                                                        var metricPartition      = metricPartitionsByPosition[partitionResult.PartitionPosition];
                                                        var metricValuePartition = new MetricValuePartition();
                                                        metricValuePartition.MetricPartition   = metricPartition;
                                                        metricValuePartition.MetricPartitionId = metricPartition.Id;
                                                        metricValuePartition.MetricValue       = metricValue;
                                                        metricValuePartition.EntityId          = partitionResult.EntityId;
                                                        metricValue.MetricValuePartitions.Add(metricValuePartition);
                                                    }
                                                }
                                            }

                                            if (metricValue.MetricValuePartitions == null || !metricValue.MetricValuePartitions.Any())
                                            {
                                                // shouldn't happen, but just in case
                                                throw new Exception("MetricValue requires at least one Partition Value");
                                            }
                                            else
                                            {
                                                metricValuesToAdd.Add(metricValue);
                                            }
                                        }

                                        // if a single metricValueDateTime was specified, delete any existing metric values for this date and refresh with the current results
                                        var dbTransaction = rockContextForMetricValues.Database.BeginTransaction();
                                        if (getMetricValueDateTimeFromResultSet)
                                        {
                                            var metricValueDateTimes = metricValuesToAdd.Select(a => a.MetricValueDateTime).Distinct().ToList();
                                            foreach (var metricValueDateTime in metricValueDateTimes)
                                            {
                                                bool alreadyHasMetricValues = metricValueService.Queryable().Where(a => a.MetricId == metric.Id && a.MetricValueDateTime == metricValueDateTime).Any();
                                                if (alreadyHasMetricValues)
                                                {
                                                    // use direct SQL to clean up any existing metric values
                                                    rockContextForMetricValues.Database.ExecuteSqlCommand(@"
                                                        DELETE
                                                        FROM MetricValuePartition
                                                        WHERE MetricValueId IN (
                                                            SELECT Id
                                                            FROM MetricValue
                                                            WHERE MetricId = @metricId
                                                            AND MetricValueDateTime = @metricValueDateTime
                                                        )
                                                    ", new SqlParameter("@metricId", metric.Id), new SqlParameter("@metricValueDateTime", metricValueDateTime));

                                                    rockContextForMetricValues.Database.ExecuteSqlCommand(@"
                                                        DELETE
                                                        FROM MetricValue
                                                        WHERE MetricId = @metricId
                                                        AND MetricValueDateTime = @metricValueDateTime
                                                    ", new SqlParameter("@metricId", metric.Id), new SqlParameter("@metricValueDateTime", metricValueDateTime));
                                                }
                                            }
                                        }

                                        metricValueService.AddRange(metricValuesToAdd);

                                        // disable savechanges PrePostProcessing since there could be hundreds or thousands of metric values getting inserted/updated
                                        rockContextForMetricValues.SaveChanges(true);
                                        dbTransaction.Commit();
                                    }

                                    rockContextForMetricEntity.SaveChanges();
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    metricExceptions.Add(new Exception(string.Format("Exception when calculating metric for {0} ", metric), ex));
                }
            }

            context.Result = string.Format("Calculated a total of {0} metric values for {1} metrics", metricValuesCalculated, metricsCalculated);

            if (metricExceptions.Any())
            {
                throw new AggregateException("One or more metric calculations failed ", metricExceptions);
            }
        }
Пример #5
0
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            int campusEntityTypeId   = EntityTypeCache.Read(typeof(Rock.Model.Campus)).Id;
            int scheduleEntityTypeId = EntityTypeCache.Read(typeof(Rock.Model.Schedule)).Id;

            int?campusId = bddlCampus.SelectedValueAsInt();
            //int? scheduleId = bddlService.SelectedValueAsInt();
            DateTime?weekend = bddlWeekend.SelectedValue.AsDateTime();

            if (campusId.HasValue && weekend.HasValue)
            {
                using (var rockContext = new RockContext())
                {
                    var metricService      = new MetricService(rockContext);
                    var metricValueService = new MetricValueService(rockContext);

                    foreach (RepeaterItem category in rptrMetricCategory.Items)
                    {
                        var rptrMetric = category.FindControl("rptrMetric") as Repeater;
                        foreach (RepeaterItem item in rptrMetric.Items)
                        {
                            var hfMetricIId   = item.FindControl("hfMetricId") as HiddenField;
                            var nbMetricValue = item.FindControl("nbMetricValue") as NumberBox;

                            if (hfMetricIId != null && nbMetricValue != null && !string.IsNullOrEmpty(nbMetricValue.Text))
                            {
                                int metricId = hfMetricIId.ValueAsInt();
                                var metric   = new MetricService(rockContext).Get(metricId);

                                if (metric != null)
                                {
                                    int campusPartitionId = metric.MetricPartitions.Where(p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == campusEntityTypeId).Select(p => p.Id).FirstOrDefault();

                                    var metricValue = metricValueService
                                                      .Queryable()
                                                      .Where(v =>
                                                             v.MetricId == metric.Id &&
                                                             v.MetricValueDateTime.HasValue && v.MetricValueDateTime.Value == weekend.Value &&
                                                             v.MetricValuePartitions.Count == 1 &&
                                                             v.MetricValuePartitions.Any(p => p.MetricPartitionId == campusPartitionId && p.EntityId.HasValue && p.EntityId.Value == campusId.Value))
                                                      .FirstOrDefault();

                                    if (metricValue == null)
                                    {
                                        metricValue = new MetricValue();
                                        metricValue.MetricValueType     = MetricValueType.Measure;
                                        metricValue.MetricId            = metric.Id;
                                        metricValue.MetricValueDateTime = weekend.Value;
                                        metricValueService.Add(metricValue);

                                        var campusValuePartition = new MetricValuePartition();
                                        campusValuePartition.MetricPartitionId = campusPartitionId;
                                        campusValuePartition.EntityId          = campusId.Value;
                                        metricValue.MetricValuePartitions.Add(campusValuePartition);
                                    }

                                    metricValue.YValue = nbMetricValue.Text.AsDecimalOrNull();
                                    metricValue.Note   = tbNote.Text;
                                }
                            }
                        }
                    }

                    foreach (RepeaterItem service in rptrService.Items)
                    {
                        var hfScheduleId      = service.FindControl("hfScheduleId") as HiddenField;
                        int scheduleId        = hfScheduleId.ValueAsInt();
                        var rptrServiceMetric = service.FindControl("pnlwService").FindControl("rptrServiceMetric") as Repeater;

                        foreach (RepeaterItem item in rptrServiceMetric.Items)
                        {
                            var hfMetricIId   = item.FindControl("hfMetricId") as HiddenField;
                            var nbMetricValue = item.FindControl("nbMetricValue") as NumberBox;

                            if (hfMetricIId != null && nbMetricValue != null && !string.IsNullOrEmpty(nbMetricValue.Text))
                            {
                                int metricId = hfMetricIId.ValueAsInt();
                                var metric   = new MetricService(rockContext).Get(metricId);

                                if (metric != null)
                                {
                                    int campusPartitionId   = metric.MetricPartitions.Where(p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == campusEntityTypeId).Select(p => p.Id).FirstOrDefault();
                                    int schedulePartitionId = metric.MetricPartitions.Where(p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == scheduleEntityTypeId).Select(p => p.Id).FirstOrDefault();

                                    var metricValue = metricValueService
                                                      .Queryable()
                                                      .Where(v =>
                                                             v.MetricId == metric.Id &&
                                                             v.MetricValueDateTime.HasValue && v.MetricValueDateTime.Value == weekend.Value &&
                                                             v.MetricValuePartitions.Count == 2 &&
                                                             v.MetricValuePartitions.Any(p => p.MetricPartitionId == campusPartitionId && p.EntityId.HasValue && p.EntityId.Value == campusId.Value) &&
                                                             v.MetricValuePartitions.Any(p => p.MetricPartitionId == schedulePartitionId && p.EntityId.HasValue && p.EntityId.Value == scheduleId))
                                                      .FirstOrDefault();

                                    if (metricValue == null)
                                    {
                                        metricValue = new MetricValue();
                                        metricValue.MetricValueType     = MetricValueType.Measure;
                                        metricValue.MetricId            = metric.Id;
                                        metricValue.MetricValueDateTime = weekend.Value;
                                        metricValueService.Add(metricValue);

                                        var campusValuePartition = new MetricValuePartition();
                                        campusValuePartition.MetricPartitionId = campusPartitionId;
                                        campusValuePartition.EntityId          = campusId.Value;
                                        metricValue.MetricValuePartitions.Add(campusValuePartition);

                                        var scheduleValuePartition = new MetricValuePartition();
                                        scheduleValuePartition.MetricPartitionId = schedulePartitionId;
                                        scheduleValuePartition.EntityId          = scheduleId;
                                        metricValue.MetricValuePartitions.Add(scheduleValuePartition);
                                    }

                                    metricValue.YValue = nbMetricValue.Text.AsDecimalOrNull();
                                    metricValue.Note   = tbNote.Text;
                                }
                            }
                        }
                    }

                    rockContext.SaveChanges();
                }

                nbMetricsSaved.Text = string.Format("Your metrics for {0} at the {1} Campus have been saved.",
                                                    bddlWeekend.SelectedItem.Text, bddlCampus.SelectedItem.Text);
                nbMetricsSaved.Visible = true;

                BindMetrics();
            }
        }
Пример #6
0
        /// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Execute(IJobExecutionContext context)
        {
            var dataMap        = context.JobDetail.JobDataMap;
            var commandTimeout = dataMap.GetString(AttributeKey.CommandTimeout).AsIntegerOrNull() ?? 300;
            var metricSourceValueTypeDataviewGuid = Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_DATAVIEW.AsGuid();
            var metricSourceValueTypeSqlGuid      = Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_SQL.AsGuid();
            var metricSourceValueTypeLavaGuid     = Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_LAVA.AsGuid();

            Guid[] calculatedSourceTypes = new Guid[] {
                metricSourceValueTypeDataviewGuid,
                metricSourceValueTypeSqlGuid,
                metricSourceValueTypeLavaGuid
            };

            var metricsQry = new MetricService(new RockContext()).Queryable().AsNoTracking().Where(
                a => a.ScheduleId.HasValue &&
                a.SourceValueTypeId.HasValue &&
                calculatedSourceTypes.Contains(a.SourceValueType.Guid));

            var metricIdList = metricsQry.OrderBy(a => a.Title).ThenBy(a => a.Subtitle).Select(a => a.Id).ToList();

            var    metricExceptions       = new List <Exception>();
            int    metricsCalculated      = 0;
            int    metricValuesCalculated = 0;
            Metric metric = null;

            foreach (var metricId in metricIdList)
            {
                try
                {
                    using (var rockContextForMetricEntity = new RockContext())
                    {
                        rockContextForMetricEntity.Database.CommandTimeout = commandTimeout;
                        var metricService = new MetricService(rockContextForMetricEntity);

                        metric = metricService.Get(metricId);

                        /*  Get the last time the metric has run, if it has never run then set it as the first day of the current week to give it a chance to run now.
                         *  NOTE: This is being used instead of Min Date to prevent a schedule with a start date of months or years back from running for each period since then.
                         *  This would be the case for the "out-of-the-box" Rock daily metrics "Active Records", "Active Families", and "Active Connection Requests" if they
                         *  have never run before. Or if a new user created metric uses a schedule that has an older start date.
                         */
                        DateTime currentDateTime = RockDateTime.Now;
                        DateTime?startOfWeek     = currentDateTime.StartOfWeek(RockDateTime.FirstDayOfWeek);
                        DateTime?lastRunDateTime = metric.LastRunDateTime ?? startOfWeek;

                        // get all the schedule times that were supposed to run since that last time it was scheduled to run
                        var scheduledDateTimesToProcess = metric.Schedule.GetScheduledStartTimes(lastRunDateTime.Value, currentDateTime).Where(a => a > lastRunDateTime.Value).ToList();
                        foreach (var scheduleDateTime in scheduledDateTimesToProcess)
                        {
                            using (var rockContextForMetricValues = new RockContext())
                            {
                                rockContextForMetricValues.Database.CommandTimeout = commandTimeout;
                                var metricPartitions                     = new MetricPartitionService(rockContextForMetricValues).Queryable().Where(a => a.MetricId == metric.Id).ToList();
                                var metricValueService                   = new MetricValueService(rockContextForMetricValues);
                                List <ResultValue> resultValues          = new List <ResultValue>();
                                bool getMetricValueDateTimeFromResultSet = false;
                                if (metric.SourceValueType.Guid == metricSourceValueTypeDataviewGuid)
                                {
                                    // get the metric value from the DataView
                                    if (metric.DataView != null)
                                    {
                                        bool parseCampusPartition = metricPartitions.Count == 1 &&
                                                                    metric.AutoPartitionOnPrimaryCampus &&
                                                                    metric.DataView.EntityTypeId == Web.Cache.EntityTypeCache.GetId(SystemGuid.EntityType.PERSON) &&
                                                                    metricPartitions[0].EntityTypeId == Web.Cache.EntityTypeCache.GetId(SystemGuid.EntityType.CAMPUS);

                                        // Dataview metrics can be partitioned by campus only and AutoPartitionOnPrimaryCampus must be selected.
                                        if (metricPartitions.Count > 1 ||
                                            (metricPartitions[0].EntityTypeId.HasValue && parseCampusPartition == false))
                                        {
                                            throw new NotImplementedException("Partitioned Metrics using DataViews is only supported for Person data views using a single partition of type 'Campus' with 'Auto Partition on Primary Campus' checked. Any other dataview partition configuration is not supported.");
                                        }

                                        Stopwatch stopwatch = Stopwatch.StartNew();
                                        var       qry       = metric.DataView.GetQuery(new DataViewGetQueryArgs());

                                        if (parseCampusPartition)
                                        {
                                            // Create a dictionary of campus IDs with a person count
                                            var campusPartitionValues = new Dictionary <int, int>();
                                            foreach (var person in qry.ToList())
                                            {
                                                var iPerson  = ( Person )person;
                                                var campusId = iPerson.GetCampus()?.Id ?? -1;
                                                campusPartitionValues.TryGetValue(campusId, out var currentCount);
                                                campusPartitionValues[campusId] = currentCount + 1;
                                            }

                                            // Use the dictionary to create the ResultValues for each campus (partition)
                                            foreach (var campusPartitionValue in campusPartitionValues)
                                            {
                                                var resultValue = new ResultValue
                                                {
                                                    MetricValueDateTime = scheduleDateTime,
                                                    Partitions          = new List <ResultValuePartition>(),
                                                    Value = campusPartitionValue.Value
                                                };

                                                int?entityId = campusPartitionValue.Key;
                                                if (entityId == -1)
                                                {
                                                    entityId = null;
                                                }

                                                resultValue.Partitions.Add(new ResultValuePartition
                                                {
                                                    PartitionPosition = 0,
                                                    EntityId          = entityId
                                                });

                                                resultValues.Add(resultValue);
                                            }
                                        }
                                        else
                                        {
                                            // Put the entire set in one result since there is no partition
                                            resultValues.Add(new ResultValue
                                            {
                                                Value = Convert.ToDecimal(qry.Count()),
                                                MetricValueDateTime = scheduleDateTime,
                                                Partitions          = new List <ResultValuePartition>()
                                            });
                                        }

                                        stopwatch.Stop();
                                        DataViewService.AddRunDataViewTransaction(metric.DataView.Id, Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds));
                                    }
                                }
                                else if (metric.SourceValueType.Guid == metricSourceValueTypeSqlGuid)
                                {
                                    //// calculate the metricValue using the results from the SQL
                                    //// assume SQL is in one of the following forms:
                                    //// -- "SELECT Count(*) FROM ..."
                                    //// -- "SELECT Count(*), [MetricValueDateTime] FROM ..."
                                    //// -- "SELECT Count(*), Partition0EntityId, Partition1EntityId, Partition2EntityId,.. FROM ..."
                                    //// -- "SELECT Count(*), [MetricValueDateTime], Partition0EntityId, Partition1EntityId, Partition2EntityId,.. FROM ..."
                                    if (!string.IsNullOrWhiteSpace(metric.SourceSql))
                                    {
                                        string formattedSql = metric.SourceSql.ResolveMergeFields(metric.GetMergeObjects(scheduleDateTime));
                                        var    tableResult  = DbService.GetDataTable(formattedSql, System.Data.CommandType.Text, null);

                                        if (tableResult.Columns.Count >= 2 && tableResult.Columns[1].ColumnName == "MetricValueDateTime")
                                        {
                                            getMetricValueDateTimeFromResultSet = true;
                                        }

                                        foreach (var row in tableResult.Rows.OfType <System.Data.DataRow>())
                                        {
                                            var resultValue = new ResultValue();

                                            resultValue.Value = Convert.ToDecimal(row[0] == DBNull.Value ? 0 : row[0]);
                                            if (getMetricValueDateTimeFromResultSet)
                                            {
                                                resultValue.MetricValueDateTime = Convert.ToDateTime(row[1]);
                                            }
                                            else
                                            {
                                                resultValue.MetricValueDateTime = scheduleDateTime;
                                            }

                                            resultValue.Partitions = new List <ResultValuePartition>();
                                            int partitionPosition    = 0;
                                            int partitionFieldIndex  = getMetricValueDateTimeFromResultSet ? 2 : 1;
                                            int partitionColumnCount = tableResult.Columns.Count - 1;
                                            while (partitionFieldIndex <= partitionColumnCount)
                                            {
                                                resultValue.Partitions.Add(new ResultValuePartition
                                                {
                                                    PartitionPosition = partitionPosition,
                                                    EntityId          = row[partitionFieldIndex] as int?
                                                });

                                                partitionPosition++;
                                                partitionFieldIndex++;
                                            }

                                            resultValues.Add(resultValue);
                                        }
                                    }
                                }
                                else if (metric.SourceValueType.Guid == metricSourceValueTypeLavaGuid)
                                {
                                    //// calculate the metricValue using the results from Lava
                                    //// assume Lava Output is in one of the following forms:
                                    //// A single Count
                                    //// 42
                                    //// A List of Count, MetricValueDateTime
                                    //// 42, 1/1/2017
                                    //// 40, 1/2/2017
                                    //// 49, 1/3/2017
                                    //// A List of Count, Partition0EntityId, Partition1EntityId, Partition2EntityId
                                    //// 42, 201, 450, 654
                                    //// 42, 202, 450, 654
                                    //// 42, 203, 450, 654
                                    //// A List of Count, MetricValueDateTime,  Partition0EntityId, Partition1EntityId, Partition2EntityId
                                    //// 42, 1/1/2017, 201, 450, 654
                                    //// 42, 1/2/2017, 202, 450, 654
                                    //// 42, 1/3/2017, 203, 450, 654
                                    if (!string.IsNullOrWhiteSpace(metric.SourceLava))
                                    {
                                        var           mergeObjects = metric.GetMergeObjects(scheduleDateTime);
                                        string        lavaResult   = metric.SourceLava.ResolveMergeFields(mergeObjects, enabledLavaCommands: "All", throwExceptionOnErrors: true);
                                        List <string> resultLines  = lavaResult.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
                                                                     .Select(a => a.Trim()).Where(a => !string.IsNullOrEmpty(a)).ToList();
                                        List <string[]> resultList = resultLines.Select(a => a.SplitDelimitedValues()).ToList();

                                        if (resultList.Any())
                                        {
                                            if (resultList[0].Length >= 2)
                                            {
                                                // if the value of the data in the 2nd column is a Date, assume that is is the MetricValueDateTime
                                                if (resultList[0][1].AsDateTime().HasValue)
                                                {
                                                    getMetricValueDateTimeFromResultSet = true;
                                                }
                                            }
                                        }

                                        foreach (var row in resultList)
                                        {
                                            var resultValue = new ResultValue();

                                            resultValue.Value = row[0].AsDecimal();
                                            if (getMetricValueDateTimeFromResultSet)
                                            {
                                                resultValue.MetricValueDateTime = row[1].AsDateTime() ?? scheduleDateTime;
                                            }
                                            else
                                            {
                                                resultValue.MetricValueDateTime = scheduleDateTime;
                                            }

                                            resultValue.Partitions = new List <ResultValuePartition>();
                                            int partitionPosition    = 0;
                                            int partitionFieldIndex  = getMetricValueDateTimeFromResultSet ? 2 : 1;
                                            int partitionColumnCount = row.Length - 1;
                                            while (partitionFieldIndex <= partitionColumnCount)
                                            {
                                                resultValue.Partitions.Add(new ResultValuePartition
                                                {
                                                    PartitionPosition = partitionPosition,
                                                    EntityId          = row[partitionFieldIndex].AsIntegerOrNull()
                                                });

                                                partitionPosition++;
                                                partitionFieldIndex++;
                                            }

                                            resultValues.Add(resultValue);
                                        }
                                    }
                                }

                                metric.LastRunDateTime = scheduleDateTime;
                                metricsCalculated++;
                                metricValuesCalculated += resultValues.Count();

                                if (resultValues.Any())
                                {
                                    List <MetricValue> metricValuesToAdd = new List <MetricValue>();
                                    foreach (var resultValue in resultValues)
                                    {
                                        var metricValue = new MetricValue();
                                        metricValue.MetricId            = metric.Id;
                                        metricValue.MetricValueDateTime = resultValue.MetricValueDateTime;
                                        metricValue.MetricValueType     = MetricValueType.Measure;
                                        metricValue.YValue                = resultValue.Value;
                                        metricValue.CreatedDateTime       = RockDateTime.Now;
                                        metricValue.ModifiedDateTime      = RockDateTime.Now;
                                        metricValue.MetricValuePartitions = new List <MetricValuePartition>();
                                        var metricPartitionsByPosition = metricPartitions.OrderBy(a => a.Order).ToList();

                                        if (!resultValue.Partitions.Any() && metricPartitionsByPosition.Count() == 1 && !metricPartitionsByPosition[0].EntityTypeId.HasValue)
                                        {
                                            // a metric with just the default partition (not partitioned by Entity)
                                            var metricPartition      = metricPartitionsByPosition[0];
                                            var metricValuePartition = new MetricValuePartition();
                                            metricValuePartition.MetricPartition   = metricPartition;
                                            metricValuePartition.MetricPartitionId = metricPartition.Id;
                                            metricValuePartition.MetricValue       = metricValue;
                                            metricValuePartition.EntityId          = null;
                                            metricValue.MetricValuePartitions.Add(metricValuePartition);
                                        }
                                        else
                                        {
                                            foreach (var partitionResult in resultValue.Partitions)
                                            {
                                                if (metricPartitionsByPosition.Count > partitionResult.PartitionPosition)
                                                {
                                                    var metricPartition      = metricPartitionsByPosition[partitionResult.PartitionPosition];
                                                    var metricValuePartition = new MetricValuePartition();
                                                    metricValuePartition.MetricPartition   = metricPartition;
                                                    metricValuePartition.MetricPartitionId = metricPartition.Id;
                                                    metricValuePartition.MetricValue       = metricValue;
                                                    metricValuePartition.EntityId          = partitionResult.EntityId;
                                                    metricValue.MetricValuePartitions.Add(metricValuePartition);
                                                }
                                            }
                                        }

                                        if (metricValue.MetricValuePartitions == null || !metricValue.MetricValuePartitions.Any())
                                        {
                                            // shouldn't happen, but just in case
                                            throw new Exception("MetricValue requires at least one Partition Value");
                                        }
                                        else
                                        {
                                            metricValuesToAdd.Add(metricValue);
                                        }
                                    }

                                    // if a single metricValueDateTime was specified, delete any existing metric values for this date and refresh with the current results
                                    var dbTransaction = rockContextForMetricValues.Database.BeginTransaction();
                                    if (getMetricValueDateTimeFromResultSet)
                                    {
                                        var metricValueDateTimes = metricValuesToAdd.Select(a => a.MetricValueDateTime).Distinct().ToList();
                                        foreach (var metricValueDateTime in metricValueDateTimes)
                                        {
                                            bool alreadyHasMetricValues = metricValueService.Queryable().Where(a => a.MetricId == metric.Id && a.MetricValueDateTime == metricValueDateTime).Any();
                                            if (alreadyHasMetricValues)
                                            {
                                                // use direct SQL to clean up any existing metric values
                                                rockContextForMetricValues.Database.ExecuteSqlCommand(@"
                                                    DELETE
                                                    FROM MetricValuePartition
                                                    WHERE MetricValueId IN (
                                                        SELECT Id
                                                        FROM MetricValue
                                                        WHERE MetricId = @metricId
                                                        AND MetricValueDateTime = @metricValueDateTime
                                                    )
                                                ", new SqlParameter("@metricId", metric.Id), new SqlParameter("@metricValueDateTime", metricValueDateTime));

                                                rockContextForMetricValues.Database.ExecuteSqlCommand(@"
                                                    DELETE
                                                    FROM MetricValue
                                                    WHERE MetricId = @metricId
                                                    AND MetricValueDateTime = @metricValueDateTime
                                                ", new SqlParameter("@metricId", metric.Id), new SqlParameter("@metricValueDateTime", metricValueDateTime));
                                            }
                                        }
                                    }

                                    metricValueService.AddRange(metricValuesToAdd);

                                    // disable savechanges PrePostProcessing since there could be hundreds or thousands of metric values getting inserted/updated
                                    rockContextForMetricValues.SaveChanges(true);
                                    dbTransaction.Commit();
                                }

                                rockContextForMetricEntity.SaveChanges();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    metricExceptions.Add(new Exception($"Exception when calculating metric for {metric}: {ex.Message}", ex));
                }
            }

            context.Result = string.Format("Calculated a total of {0} metric values for {1} metrics", metricValuesCalculated, metricsCalculated);

            if (metricExceptions.Any())
            {
                throw new AggregateException("One or more metric calculations failed ", metricExceptions);
            }
        }
Пример #7
0
        /// <summary>
        /// Executes the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Execute( IJobExecutionContext context )
        {
            var metricSourceValueTypeDataviewGuid = Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_DATAVIEW.AsGuid();
            var metricSourceValueTypeSqlGuid = Rock.SystemGuid.DefinedValue.METRIC_SOURCE_VALUE_TYPE_SQL.AsGuid();

            var metricsQry = new MetricService( new RockContext() ).Queryable().AsNoTracking().Where(
                a => a.ScheduleId.HasValue
                && a.SourceValueTypeId.HasValue
                && ( a.SourceValueType.Guid == metricSourceValueTypeDataviewGuid || a.SourceValueType.Guid == metricSourceValueTypeSqlGuid ) );

            var metricIdList = metricsQry.OrderBy( a => a.Title ).ThenBy( a => a.Subtitle ).Select( a => a.Id ).ToList();

            var metricExceptions = new List<Exception>();
            int metricsCalculated = 0;
            int metricValuesCalculated = 0;
            Metric metric = null;

            foreach ( var metricId in metricIdList )
            {
                try
                {
                    using ( var rockContextForMetricEntity = new RockContext() )
                    {
                        var metricService = new MetricService( rockContextForMetricEntity );

                        metric = metricService.Get( metricId );
                        var lastRunDateTime = metric.LastRunDateTime ?? metric.CreatedDateTime ?? metric.ModifiedDateTime;
                        if ( lastRunDateTime.HasValue )
                        {
                            var currentDateTime = RockDateTime.Now;

                            // get all the schedule times that were supposed to run since that last time it was scheduled to run
                            var scheduledDateTimesToProcess = metric.Schedule.GetScheduledStartTimes( lastRunDateTime.Value, currentDateTime ).Where( a => a > lastRunDateTime.Value ).ToList();
                            foreach ( var scheduleDateTime in scheduledDateTimesToProcess )
                            {
                                using ( var rockContextForMetricValues = new RockContext() )
                                {
                                    var metricPartitions = new MetricPartitionService( rockContextForMetricValues ).Queryable().Where( a => a.MetricId == metric.Id ).ToList();
                                    var metricValueService = new MetricValueService( rockContextForMetricValues );
                                    List<ResultValue> resultValues = new List<ResultValue>();
                                    bool getMetricValueDateTimeFromResultSet = false;
                                    if ( metric.SourceValueType.Guid == metricSourceValueTypeDataviewGuid )
                                    {
                                        // get the metric value from the DataView
                                        if ( metric.DataView != null )
                                        {
                                            var errorMessages = new List<string>();
                                            var qry = metric.DataView.GetQuery( null, null, out errorMessages );
                                            if ( metricPartitions.Count > 1 || metricPartitions.First().EntityTypeId.HasValue )
                                            {
                                                throw new NotImplementedException( "Partitioned Metrics using DataViews is not supported." );
                                            }
                                            else
                                            {
                                                var resultValue = new ResultValue();
                                                resultValue.Value = Convert.ToDecimal( qry.Count() );
                                                resultValue.Partitions = new List<ResultValuePartition>();
                                                resultValue.MetricValueDateTime = scheduleDateTime;
                                                resultValues.Add( resultValue );
                                            }
                                        }
                                    }
                                    else if ( metric.SourceValueType.Guid == metricSourceValueTypeSqlGuid )
                                    {
                                        //// calculate the metricValue using the results from the SQL
                                        //// assume SQL is in one of the following forms:
                                        //// -- "SELECT Count(*), Partion0EntityId, Partion1EntityId, Partion2EntityId,.. FROM ..."
                                        //// -- "SELECT Count(*), [MetricValueDateTime], Partion0EntityId, Partion1EntityId, Partion2EntityId,.. FROM ..."
                                        if ( !string.IsNullOrWhiteSpace( metric.SourceSql ) )
                                        {
                                            string formattedSql = metric.SourceSql.ResolveMergeFields( metric.GetMergeObjects( scheduleDateTime ) );
                                            var tableResult = DbService.GetDataTable( formattedSql, System.Data.CommandType.Text, null );

                                            if ( tableResult.Columns.Count >= 2 && tableResult.Columns[1].ColumnName == "MetricValueDateTime" )
                                            {
                                                getMetricValueDateTimeFromResultSet = true;
                                            }

                                            foreach ( var row in tableResult.Rows.OfType<System.Data.DataRow>() )
                                            {
                                                var resultValue = new ResultValue();

                                                resultValue.Value = Convert.ToDecimal( row[0] );
                                                if ( getMetricValueDateTimeFromResultSet )
                                                {
                                                    resultValue.MetricValueDateTime = Convert.ToDateTime( row[1] );
                                                }
                                                else
                                                {
                                                    resultValue.MetricValueDateTime = scheduleDateTime;
                                                }

                                                resultValue.Partitions = new List<ResultValuePartition>();
                                                int partitionPosition = 0;
                                                int partitionFieldIndex = getMetricValueDateTimeFromResultSet ? 2 : 1;
                                                int partitionColumnCount = tableResult.Columns.Count - 1;
                                                while ( partitionFieldIndex <= partitionColumnCount )
                                                {
                                                    resultValue.Partitions.Add( new ResultValuePartition
                                                    {
                                                        PartitionPosition = partitionPosition,
                                                        EntityId = row[partitionFieldIndex] as int?
                                                    } );

                                                    partitionPosition++;
                                                    partitionFieldIndex++;
                                                }

                                                resultValues.Add( resultValue );
                                            }
                                        }
                                    }

                                    metric.LastRunDateTime = scheduleDateTime;
                                    metricsCalculated++;
                                    metricValuesCalculated += resultValues.Count();

                                    if ( resultValues.Any() )
                                    {
                                        List<MetricValue> metricValuesToAdd = new List<MetricValue>();
                                        foreach ( var resultValue in resultValues )
                                        {
                                            var metricValue = new MetricValue();
                                            metricValue.MetricId = metric.Id;
                                            metricValue.MetricValueDateTime = resultValue.MetricValueDateTime;
                                            metricValue.MetricValueType = MetricValueType.Measure;
                                            metricValue.YValue = resultValue.Value;
                                            metricValue.CreatedDateTime = RockDateTime.Now;
                                            metricValue.ModifiedDateTime = RockDateTime.Now;
                                            metricValue.MetricValuePartitions = new List<MetricValuePartition>();
                                            var metricPartitionsByPosition = metricPartitions.OrderBy( a => a.Order ).ToList();

                                            if ( !resultValue.Partitions.Any() && metricPartitionsByPosition.Count() == 1 && !metricPartitionsByPosition[0].EntityTypeId.HasValue )
                                            {
                                                // a metric with just the default partition (not partitioned by Entity)
                                                var metricPartition = metricPartitionsByPosition[0];
                                                var metricValuePartition = new MetricValuePartition();
                                                metricValuePartition.MetricPartition = metricPartition;
                                                metricValuePartition.MetricPartitionId = metricPartition.Id;
                                                metricValuePartition.MetricValue = metricValue;
                                                metricValuePartition.EntityId = null;
                                                metricValue.MetricValuePartitions.Add( metricValuePartition );
                                            }
                                            else
                                            {
                                                foreach ( var partitionResult in resultValue.Partitions )
                                                {
                                                    if ( metricPartitionsByPosition.Count > partitionResult.PartitionPosition )
                                                    {
                                                        var metricPartition = metricPartitionsByPosition[partitionResult.PartitionPosition];
                                                        var metricValuePartition = new MetricValuePartition();
                                                        metricValuePartition.MetricPartition = metricPartition;
                                                        metricValuePartition.MetricPartitionId = metricPartition.Id;
                                                        metricValuePartition.MetricValue = metricValue;
                                                        metricValuePartition.EntityId = partitionResult.EntityId;
                                                        metricValue.MetricValuePartitions.Add( metricValuePartition );
                                                    }
                                                }
                                            }

                                            if ( metricValue.MetricValuePartitions == null || !metricValue.MetricValuePartitions.Any() )
                                            {
                                                // shouldn't happen, but just in case
                                                throw new Exception( "MetricValue requires at least one Partition Value" );
                                            }
                                            else
                                            {
                                                metricValuesToAdd.Add( metricValue );
                                            }
                                        }

                                        // if a single metricValueDateTime was specified, delete any existing metric values for this date and refresh with the current results
                                        var dbTransaction = rockContextForMetricValues.Database.BeginTransaction();
                                        if ( getMetricValueDateTimeFromResultSet )
                                        {
                                            var metricValueDateTimes = metricValuesToAdd.Select( a => a.MetricValueDateTime ).Distinct().ToList();
                                            foreach ( var metricValueDateTime in metricValueDateTimes )
                                            {
                                                bool alreadyHasMetricValues = metricValueService.Queryable().Where( a => a.MetricId == metric.Id && a.MetricValueDateTime == metricValueDateTime ).Any();
                                                if ( alreadyHasMetricValues )
                                                {
                                                    // use direct SQL to clean up any existing metric values
                                                    rockContextForMetricValues.Database.ExecuteSqlCommand( @"
                                                        DELETE
                                                        FROM MetricValuePartition
                                                        WHERE MetricValueId IN (
                                                            SELECT Id
                                                            FROM MetricValue
                                                            WHERE MetricId = @metricId
                                                            AND MetricValueDateTime = @metricValueDateTime
                                                        )
                                                    ", new SqlParameter( "@metricId", metric.Id ), new SqlParameter( "@metricValueDateTime", metricValueDateTime ) );

                                                    rockContextForMetricValues.Database.ExecuteSqlCommand( @"
                                                        DELETE
                                                        FROM MetricValue
                                                        WHERE MetricId = @metricId
                                                        AND MetricValueDateTime = @metricValueDateTime
                                                    ", new SqlParameter( "@metricId", metric.Id ), new SqlParameter( "@metricValueDateTime", metricValueDateTime ) );
                                                }
                                            }
                                        }

                                        metricValueService.AddRange( metricValuesToAdd );

                                        // disable savechanges PrePostProcessing since there could be hundreds or thousands of metric values getting inserted/updated
                                        rockContextForMetricValues.SaveChanges( true );
                                        dbTransaction.Commit();
                                    }

                                    rockContextForMetricEntity.SaveChanges();
                                }
                            }
                        }
                    }
                }
                catch ( Exception ex )
                {
                    metricExceptions.Add( new Exception( string.Format( "Exception when calculating metric for {0} ", metric ), ex ) );
                }
            }

            context.Result = string.Format( "Calculated a total of {0} metric values for {1} metrics", metricValuesCalculated, metricsCalculated );

            if ( metricExceptions.Any() )
            {
                throw new AggregateException( "One or more metric calculations failed ", metricExceptions );
            }
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            int campusEntityTypeId   = EntityTypeCache.Get(typeof(Rock.Model.Campus)).Id;
            int scheduleEntityTypeId = EntityTypeCache.Get(typeof(Rock.Model.Schedule)).Id;

            int?     campusId   = bddlCampus.SelectedValueAsInt();
            int?     scheduleId = bddlService.SelectedValueAsInt();
            DateTime?weekend    = bddlWeekend.SelectedValue.AsDateTime();

            if (campusId.HasValue && scheduleId.HasValue && weekend.HasValue)
            {
                using (var rockContext = new RockContext())
                {
                    var metricService      = new MetricService(rockContext);
                    var metricValueService = new MetricValueService(rockContext);

                    weekend = GetWeekendDate(scheduleId, weekend, rockContext);

                    foreach (RepeaterItem item in rptrMetric.Items)
                    {
                        var hfMetricIId   = item.FindControl("hfMetricId") as HiddenField;
                        var nbMetricValue = item.FindControl("nbMetricValue") as NumberBox;

                        if (hfMetricIId != null && nbMetricValue != null)
                        {
                            var metricYValue = nbMetricValue.Text.AsDecimalOrNull();

                            // If no value was provided and the block is not configured to default to "0" then just skip this metric.
                            if (metricYValue == null && !GetAttributeValue(AttributeKey.DefaultToZero).AsBoolean())
                            {
                                continue;
                            }

                            int metricId = hfMetricIId.ValueAsInt();
                            var metric   = new MetricService(rockContext).Get(metricId);

                            if (metric != null)
                            {
                                int campusPartitionId   = metric.MetricPartitions.Where(p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == campusEntityTypeId).Select(p => p.Id).FirstOrDefault();
                                int schedulePartitionId = metric.MetricPartitions.Where(p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == scheduleEntityTypeId).Select(p => p.Id).FirstOrDefault();

                                var metricValue = metricValueService
                                                  .Queryable()
                                                  .Where(v =>
                                                         v.MetricId == metric.Id &&
                                                         v.MetricValueDateTime.HasValue && v.MetricValueDateTime.Value == weekend.Value &&
                                                         v.MetricValuePartitions.Count == 2 &&
                                                         v.MetricValuePartitions.Any(p => p.MetricPartitionId == campusPartitionId && p.EntityId.HasValue && p.EntityId.Value == campusId.Value) &&
                                                         v.MetricValuePartitions.Any(p => p.MetricPartitionId == schedulePartitionId && p.EntityId.HasValue && p.EntityId.Value == scheduleId.Value))
                                                  .FirstOrDefault();

                                if (metricValue == null)
                                {
                                    metricValue = new MetricValue();
                                    metricValue.MetricValueType     = MetricValueType.Measure;
                                    metricValue.MetricId            = metric.Id;
                                    metricValue.MetricValueDateTime = weekend.Value;
                                    metricValueService.Add(metricValue);

                                    var campusValuePartition = new MetricValuePartition();
                                    campusValuePartition.MetricPartitionId = campusPartitionId;
                                    campusValuePartition.EntityId          = campusId.Value;
                                    metricValue.MetricValuePartitions.Add(campusValuePartition);

                                    var scheduleValuePartition = new MetricValuePartition();
                                    scheduleValuePartition.MetricPartitionId = schedulePartitionId;
                                    scheduleValuePartition.EntityId          = scheduleId.Value;
                                    metricValue.MetricValuePartitions.Add(scheduleValuePartition);
                                }

                                if (metricYValue == null)
                                {
                                    metricValue.YValue = 0;
                                }
                                else
                                {
                                    metricValue.YValue = metricYValue;
                                }

                                metricValue.Note = tbNote.Text;
                            }
                        }
                    }

                    rockContext.SaveChanges();
                }

                nbMetricsSaved.Text = string.Format("Your metrics for the {0} service on {1} at the {2} Campus have been saved.",
                                                    bddlService.SelectedItem.Text, bddlWeekend.SelectedItem.Text, bddlCampus.SelectedItem.Text);
                nbMetricsSaved.Visible = true;

                BindMetrics();
            }
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            int groupEntityTypeId  = EntityTypeCache.Get(typeof(Rock.Model.Group)).Id;
            int campusEntityTypeId = EntityTypeCache.Get(typeof(Rock.Model.Campus)).Id;

            int?     groupId = gpSelectGroup.SelectedValueAsInt();
            DateTime?dateVal = dpMetricValueDateTime.SelectedDate;

            if (groupId.HasValue && dateVal.HasValue)
            {
                using (var rockContext = new RockContext())
                {
                    var metricService      = new MetricService(rockContext);
                    var metricValueService = new MetricValueService(rockContext);

                    var group    = new GroupService(rockContext).Queryable().FirstOrDefault(g => g.Id == groupId);
                    int?campusId = group.CampusId;

                    foreach (RepeaterItem item in rptrMetric.Items)
                    {
                        var hfMetricIId   = item.FindControl("hfMetricId") as HiddenField;
                        var nbMetricValue = item.FindControl("nbMetricValue") as NumberBox;

                        if (hfMetricIId != null && nbMetricValue != null)
                        {
                            int metricId = hfMetricIId.ValueAsInt();
                            var metric   = new MetricService(rockContext).Get(metricId);

                            if (metric != null)
                            {
                                int groupPartitionId  = metric.MetricPartitions.Where(p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == groupEntityTypeId).Select(p => p.Id).FirstOrDefault();
                                int campusPartitionId = metric.MetricPartitions.Where(p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == campusEntityTypeId).Select(p => p.Id).FirstOrDefault();

                                var metricValue = metricValueService
                                                  .Queryable()
                                                  .Where(v =>
                                                         v.MetricId == metric.Id &&
                                                         v.MetricValueDateTime.HasValue && v.MetricValueDateTime.Value == dateVal.Value &&
                                                         (
                                                             (
                                                                 v.MetricValuePartitions.Count == 2 &&
                                                                 v.MetricValuePartitions.Any(p => p.MetricPartitionId == campusPartitionId && p.EntityId.HasValue && p.EntityId.Value == campusId.Value) &&
                                                                 v.MetricValuePartitions.Any(p => p.MetricPartitionId == groupPartitionId && p.EntityId.HasValue && p.EntityId.Value == groupId.Value)
                                                             ) ||
                                                             (
                                                                 v.MetricValuePartitions.Count == 1 &&
                                                                 (
                                                                     v.MetricValuePartitions.Any(p => p.MetricPartitionId == groupPartitionId && p.EntityId.HasValue && p.EntityId.Value == groupId.Value)
                                                                 )
                                                             )
                                                         )
                                                         )
                                                  .FirstOrDefault();

                                if (metricValue == null)
                                {
                                    metricValue = new MetricValue();
                                    metricValue.MetricValueType     = MetricValueType.Measure;
                                    metricValue.MetricId            = metric.Id;
                                    metricValue.MetricValueDateTime = dateVal.Value;
                                    metricValueService.Add(metricValue);

                                    if (groupPartitionId > 0)
                                    {
                                        var groupValuePartition = new MetricValuePartition();
                                        groupValuePartition.MetricPartitionId = groupPartitionId;
                                        groupValuePartition.EntityId          = groupId.Value;
                                        metricValue.MetricValuePartitions.Add(groupValuePartition);
                                    }
                                    if (campusPartitionId > 0 && campusId.HasValue)
                                    {
                                        var campusValuePartition = new MetricValuePartition();
                                        campusValuePartition.MetricPartitionId = campusPartitionId;
                                        campusValuePartition.EntityId          = campusId.Value;
                                        metricValue.MetricValuePartitions.Add(campusValuePartition);
                                    }
                                }

                                metricValue.YValue = nbMetricValue.Text.AsDecimalOrNull();
                                metricValue.Note   = tbNote.Text;
                            }
                        }
                    }

                    rockContext.SaveChanges();
                }

                nbMetricsSaved.Text    = string.Format("The metrics for '{0}' on {1} have been saved.", gpSelectGroup.ItemName, dpMetricValueDateTime.SelectedDate.ToString());
                nbMetricsSaved.Visible = true;

                BindMetrics();
            }
        }
Пример #10
0
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnSave_Click( object sender, EventArgs e )
        {
            int campusEntityTypeId = EntityTypeCache.Read( typeof( Rock.Model.Campus ) ).Id;
            int scheduleEntityTypeId = EntityTypeCache.Read( typeof( Rock.Model.Schedule ) ).Id;

            int? campusId = bddlCampus.SelectedValueAsInt();
            int? scheduleId = bddlService.SelectedValueAsInt();
            DateTime? weekend = bddlWeekend.SelectedValue.AsDateTime();

            if ( campusId.HasValue && scheduleId.HasValue && weekend.HasValue )
            {
                using ( var rockContext = new RockContext() )
                {
                    var metricService = new MetricService( rockContext );
                    var metricValueService = new MetricValueService( rockContext );

                    foreach ( RepeaterItem item in rptrMetric.Items )
                    {
                        var hfMetricIId = item.FindControl( "hfMetricId" ) as HiddenField;
                        var nbMetricValue = item.FindControl( "nbMetricValue" ) as NumberBox;

                        if ( hfMetricIId != null && nbMetricValue != null  )
                        {
                            int metricId = hfMetricIId.ValueAsInt();
                            var metric = new MetricService( rockContext ).Get( metricId );

                            if ( metric != null )
                            {
                                int campusPartitionId = metric.MetricPartitions.Where( p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == campusEntityTypeId ).Select( p => p.Id ).FirstOrDefault();
                                int schedulePartitionId = metric.MetricPartitions.Where( p => p.EntityTypeId.HasValue && p.EntityTypeId.Value == scheduleEntityTypeId ).Select( p => p.Id ).FirstOrDefault();

                                var metricValue = metricValueService
                                    .Queryable()
                                    .Where( v =>
                                        v.MetricId == metric.Id &&
                                        v.MetricValueDateTime.HasValue && v.MetricValueDateTime.Value == weekend.Value &&
                                        v.MetricValuePartitions.Count == 2 &&
                                        v.MetricValuePartitions.Any( p => p.MetricPartitionId == campusPartitionId && p.EntityId.HasValue && p.EntityId.Value == campusId.Value ) &&
                                        v.MetricValuePartitions.Any( p => p.MetricPartitionId == schedulePartitionId && p.EntityId.HasValue && p.EntityId.Value == scheduleId.Value ) )
                                    .FirstOrDefault();

                                if ( metricValue == null )
                                {
                                    metricValue = new MetricValue();
                                    metricValue.MetricValueType = MetricValueType.Measure;
                                    metricValue.MetricId = metric.Id;
                                    metricValue.MetricValueDateTime = weekend.Value;
                                    metricValueService.Add( metricValue );

                                    var campusValuePartition = new MetricValuePartition();
                                    campusValuePartition.MetricPartitionId = campusPartitionId;
                                    campusValuePartition.EntityId = campusId.Value;
                                    metricValue.MetricValuePartitions.Add( campusValuePartition );

                                    var scheduleValuePartition = new MetricValuePartition();
                                    scheduleValuePartition.MetricPartitionId = schedulePartitionId;
                                    scheduleValuePartition.EntityId = scheduleId.Value;
                                    metricValue.MetricValuePartitions.Add( scheduleValuePartition );
                                }

                                metricValue.YValue = nbMetricValue.Text.AsDecimalOrNull();
                                metricValue.Note = tbNote.Text;
                            }
                        }
                    }

                    rockContext.SaveChanges();
                }

                nbMetricsSaved.Text = string.Format( "Your metrics for the {0} service on {1} at the {2} Campus have been saved.",
                    bddlService.SelectedItem.Text, bddlWeekend.SelectedItem.Text, bddlCampus.SelectedItem.Text );
                nbMetricsSaved.Visible = true;

                BindMetrics();

            }
        }