private Select GetParticipantsAnalyticsSelect(ParticipantsAnalyticsRequest analyticsRequest)
        {
            var select = new Select(UserConnection)
                         .Column("cp", "CampaignItemId")
                         .Column("cp", "StepCompleted")
                         .Column("cp", "StatusId")
                         .Column(Func.Count("cp", "CampaignItemId")).As("Count")
                         .From("CampaignParticipant").As("cp")
                         .Where("cp", "CampaignId").IsEqual(Column.Parameter(analyticsRequest.CampaignId))
                         .GroupBy("cp", "CampaignItemId")
                         .GroupBy("cp", "StatusId")
                         .GroupBy("cp", "StepCompleted") as Select;

            select.SpecifyNoLockHints();
            if (analyticsRequest.UseTimeFilters)
            {
                var filterStartDateCondition = select.AddCondition(select.SourceExpression.Alias, "CreatedOn",
                                                                   LogicalOperation.And);
                filterStartDateCondition.IsGreaterOrEqual(Column.Parameter(analyticsRequest.FilterStartDate));
                var filterDueDateCondition = select.AddCondition(select.SourceExpression.Alias, "CreatedOn",
                                                                 LogicalOperation.And);
                filterDueDateCondition.IsLessOrEqual(Column.Parameter(analyticsRequest.FilterDueDate));
            }
            return(select);
        }
 /// <summary>
 /// Swaps <see cref="ParticipantsAnalyticsRequest.FilterStartDate"/> and
 /// <see cref="ParticipantsAnalyticsRequest.FilterDueDate"/>
 /// when first greater than second.
 /// </summary>
 /// <param name="request">Instance of <see cref="ParticipantsAnalyticsRequest"/>.</param>
 private void NormalizeFilterDatesOrder(ref ParticipantsAnalyticsRequest request)
 {
     if (request.FilterStartDate > request.FilterDueDate)
     {
         var tmpStartDate = request.FilterStartDate;
         request.FilterStartDate = request.FilterDueDate;
         request.FilterDueDate   = tmpStartDate;
     }
 }
        /// <summary>
        /// Calculates campaign participant analytics by <paramref name="analyticsRequest"/>.
        /// Calculates participants count with completed and non completed flags for each campaign item.
        /// </summary>
        /// <param name="analyticsRequest">Instance of <see cref="ParticipantsAnalyticsRequest"/>.
        /// Contains parameters for calculate analytics.</param>
        /// <returns>Returns <see cref="ParticipantsAnalyticsResponse"/> instance.</returns>
        public ParticipantsAnalyticsResponse GetParticipantsAnalytics(ParticipantsAnalyticsRequest analyticsRequest)
        {
            var response = new ParticipantsAnalyticsResponse {
                CampaignId = analyticsRequest.CampaignId
            };

            NormalizeFilterDatesOrder(ref analyticsRequest);
            var analyticsSelect = GetParticipantsAnalyticsSelect(analyticsRequest);

            response.AnalyticsItems = GetParticipantsAnalyticsItems(analyticsSelect);
            return(response);
        }