Beispiel #1
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion = await GetCriterionAsync(request);

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };

            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object> {
                "System Name",
                "Program Name",
                "Registered Users",
                "Achievers"
            };

            var translations      = new Dictionary <string, ICollection <int?> >();
            var translationTotals = new Dictionary <string, long>();

            var system = await _systemRepository.GetByIdAsync((int)criterion.SystemId);

            var programDictionary = (await _programRepository.GetAllAsync((int)criterion.SiteId))
                                    .ToDictionary(_ => _.Id, _ => _.Name);

            foreach (var programId in programDictionary.Keys)
            {
                var pointTranslation = await _pointTranslationRepository
                                       .GetByProgramIdAsync(programId);

                string description = pointTranslation.ActivityDescriptionPlural;

                if (!translations.ContainsKey(description))
                {
                    translations.Add(description, new List <int?> {
                        pointTranslation.Id
                    });
                    translationTotals.Add(description, 0);
                    if (description.Length > 2)
                    {
                        headerRow.Add(description[0]
                                      .ToString()
                                      .ToUpper(System.Globalization.CultureInfo.InvariantCulture)
                                      + description[1..]);
Beispiel #2
0
        private IEnumerable <StoredReport> GetArchiveInternal(string reportName = null)
        {
            IList <StoredReport> reports = null;

            string blobConnectionString = CloudConfigurationManager.GetSetting("blobConnectionString");
            string reportBlobContainer  = CloudConfigurationManager.GetSetting("reportBlobContainer");
            string blobEndPoint         = CloudConfigurationManager.GetSetting("blobEndPoint");
            string blobPrefix           = blobEndPoint + reportBlobContainer + "/";

            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(blobConnectionString);
            CloudBlobClient     blobClient     = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer  container      = blobClient.GetContainerReference(reportBlobContainer);

            if (!container.Exists())
            {
                return(null);
            }

            string reportArchiveDir = archiveBlobPath;

            if (reportName != null)
            {
                reportArchiveDir +=
                    ((archiveBlobPath.EndsWith("/") && reportName.StartsWith("/")) ? reportName.Substring(1) : reportName);
            }
            if (!reportArchiveDir.EndsWith("/"))
            {
                reportArchiveDir += "/";
            }
            reportArchiveDir.ToLower();
            CloudBlobDirectory          archiveDir = container.GetDirectoryReference(reportArchiveDir);
            IEnumerable <IListBlobItem> archBlobs  = archiveDir.ListBlobs(true);

            foreach (ICloudBlob archBlob in archBlobs)
            {
                string thisReportName, thisReportFormat;
                thisReportName = archBlob.Name.Substring(archiveBlobPath.Length - 1);
                int extStarts = thisReportName.LastIndexOf(".");
                thisReportFormat = thisReportName.Substring(extStarts + 1);
                thisReportName   = thisReportName.Substring(0, extStarts);
                StoredReport report = new StoredReport();
                report.Name         = thisReportName;
                report.Format       = thisReportFormat;
                report.Path         = blobPrefix + archBlob.Name;
                report.ModifiedDate = archBlob.Properties.LastModified == null ?
                                      DateTime.MinValue : ((DateTimeOffset)archBlob.Properties.LastModified).UtcDateTime;
                if (reports == null)
                {
                    reports = new List <StoredReport>();
                }
                reports.Add(report);
            }

            return(reports);
        }
Beispiel #3
0
        private IEnumerable <StoredReport> GetLatestInternal(string reportName = null)
        {
            IList <StoredReport> reports = null;

            string blobConnectionString = CloudConfigurationManager.GetSetting("blobConnectionString");
            string reportBlobContainer  = CloudConfigurationManager.GetSetting("reportBlobContainer");
            string blobEndPoint         = CloudConfigurationManager.GetSetting("blobEndPoint");
            string blobPrefix           = blobEndPoint + reportBlobContainer + "/";

            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(blobConnectionString);
            CloudBlobClient     blobClient     = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer  container      = blobClient.GetContainerReference(reportBlobContainer);

            if (!container.Exists())
            {
                return(null);
            }
            CloudBlobDirectory reportDir = container.GetDirectoryReference(reportBlobPath);

            IEnumerable <IListBlobItem> blobs = reportDir.ListBlobs(true);

            foreach (ICloudBlob blob in blobs)
            {
                string thisReportName, thisReportFormat;
                thisReportName = blob.Name.Substring(reportBlobPath.Length - 1);
                int extStarts = thisReportName.LastIndexOf(".");
                thisReportFormat = thisReportName.Substring(extStarts + 1);
                thisReportName   = thisReportName.Substring(0, extStarts);
                if ((reportName != null) && (String.Compare(thisReportName, reportName, true) != 0))
                {
                    continue;
                }
                StoredReport report = new StoredReport();
                report.Name         = thisReportName;
                report.Format       = thisReportFormat;
                report.Path         = blobPrefix + blob.Name;
                report.ModifiedDate = blob.Properties.LastModified == null ?
                                      DateTime.MinValue : ((DateTimeOffset)blob.Properties.LastModified).UtcDateTime;
                if (reports == null)
                {
                    reports = new List <StoredReport>();
                }
                reports.Add(report);
            }

            return(reports);
        }
Beispiel #4
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            var report     = new StoredReport();
            var reportData = new List <object[]>();

            int count = 0;
            #endregion Reporting initialization

            #region Adjust report criteria as needed
            IEnumerable <int> badgeIds     = null;
            IEnumerable <int> challengeIds = null;

            if (!string.IsNullOrEmpty(criterion.BadgeRequiredList))
            {
                try
                {
                    badgeIds = criterion.BadgeRequiredList.Split(',').Select(int.Parse);
                }
                catch (Exception ex)
                {
                    _logger.LogError($"Unable to convert badge id list to numbers: {ex.Message}");
                    _logger.LogError($"Badge id list: {criterion.BadgeRequiredList}");
                }
            }

            if (!string.IsNullOrEmpty(criterion.ChallengeRequiredList))
            {
                try
                {
                    challengeIds = criterion.ChallengeRequiredList.Split(',').Select(int.Parse);
                }
                catch (Exception ex)
                {
                    _logger.LogError($"Unable to convert challenge id list to numbers: {ex.Message}");
                    _logger.LogError($"Challenge id list: {criterion.BadgeRequiredList}");
                }
            }

            int totalCount = challengeIds?.Count() ?? 0;
            totalCount += badgeIds?.Count() ?? 0;
            #endregion Adjust report criteria as needed

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Earned Item",
                "Participants"
            };

            // running totals
            long totalEarnedItems = 0;

            if (badgeIds != null)
            {
                foreach (var badgeId in badgeIds)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    var badgeName = await _badgeRepository.GetBadgeNameAsync(badgeId);

                    var earned = await _userLogRepository.EarnedBadgeCountAsync(criterion, badgeId);

                    UpdateProgress(progress,
                                   ++count * 100 / totalCount,
                                   $"Processing badge: {badgeName}...",
                                   request.Name);

                    reportData.Add(new object[]
                    {
                        badgeName,
                        earned
                    });

                    totalEarnedItems += earned;
                }
            }

            if (challengeIds != null)
            {
                foreach (var challengeId in challengeIds)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    var challenge = await _challengeRepository.GetByIdAsync(challengeId);

                    var earned = await _userLogRepository.CompletedChallengeCountAsync(criterion, challengeId);

                    UpdateProgress(progress,
                                   ++count * 100 / totalCount,
                                   $"Processing challenge: {challenge.Name}...",
                                   request.Name);

                    reportData.Add(new object[]
                    {
                        challenge.Name,
                        earned
                    });

                    totalEarnedItems += earned;
                }
            }

            report.Data = reportData.OrderByDescending(_ => _[1]);

            report.FooterRow = new object[]
            {
                "Total",
                totalEarnedItems
            };
            report.AsOf = _serviceFacade.DateTimeProvider.Now;
            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
Beispiel #5
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Adjust report criteria as needed
            int?badgeId     = null;
            int?challengeId = null;

            if (!string.IsNullOrEmpty(criterion.BadgeRequiredList))
            {
                try
                {
                    badgeId = Convert.ToInt32(criterion.BadgeRequiredList);
                }
                catch (Exception ex)
                {
                    _logger.LogError($"Unable to convert badge id to number: {ex.Message}");
                    _logger.LogError($"Badge id: {criterion.BadgeRequiredList}");
                }
            }

            if (!string.IsNullOrEmpty(criterion.ChallengeRequiredList))
            {
                try
                {
                    challengeId = Convert.ToInt32(criterion.ChallengeRequiredList);
                }
                catch (Exception ex)
                {
                    _logger.LogError($"Unable to convert challenge id to number: {ex.Message}");
                    _logger.LogError($"Challenge id: {criterion.BadgeRequiredList}");
                }
            }

            if (criterion.StartDate == null)
            {
                criterion.StartDate = DateTime.MinValue;
            }

            if (criterion.EndDate == null)
            {
                criterion.EndDate = DateTime.MaxValue;
            }

            #endregion Adjust report criteria as needed

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Rank",
                "Participant",
                "System Name",
                "Branch Name",
                "Program",
                "Points Earned"
            };

            ICollection <int> usersWhoEarned = null;

            if (badgeId != null && !token.IsCancellationRequested)
            {
                UpdateProgress(progress, 1, "Looking up users who earned the badge...", request.Name);

                var earned = await _userLogRepository.UserIdsEarnedBadgeAsync(badgeId.Value, criterion);

                usersWhoEarned = earned;
            }

            if (challengeId != null && !token.IsCancellationRequested)
            {
                UpdateProgress(progress, 1, "Looking up users who completed the challenge...", request.Name);

                var earned
                    = await _userLogRepository.UserIdsCompletedChallengesAsync(challengeId.Value, criterion);

                if (usersWhoEarned == null || usersWhoEarned.Count == 0)
                {
                    usersWhoEarned = earned;
                }
                else
                {
                    usersWhoEarned = usersWhoEarned.Union(earned).ToList();
                }
            }

            int  count       = 0;
            long totalPoints = 0;

            foreach (int userId in usersWhoEarned)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                UpdateProgress(progress,
                               ++count * 100 / usersWhoEarned.Count,
                               $"Processing user: {count}/{usersWhoEarned.Count}",
                               request.Name);

                long pointsEarned = await _userLogRepository.GetEarningsOverPeriodAsync(userId, criterion);

                var user = await _userRepository.GetByIdAsync(userId);

                var name = new StringBuilder(user.FirstName);
                if (!string.IsNullOrEmpty(user.LastName))
                {
                    name.Append(' ').Append(user.LastName);
                }
                if (!string.IsNullOrEmpty(user.Username))
                {
                    name.Append(" (").Append(user.Username).Append(')');
                }

                reportData.Add(new object[]
                {
                    0,
                    name.ToString(),
                    user.SystemName,
                    user.BranchName,
                    user.ProgramName,
                    pointsEarned
                });

                totalPoints += pointsEarned;
            }

            int rank = 1;
            report.Data = reportData
                          .OrderByDescending(_ => _[5])
                          .Select(_ => new object[] {
                rank++,
                _[1],
                _[2],
                _[3],
                _[4],
                _[5],
            });

            report.FooterRow = new object[]
            {
                "Total",
                string.Empty,
                string.Empty,
                string.Empty,
                string.Empty,
                totalPoints
            };
            report.AsOf = _serviceFacade.DateTimeProvider.Now;
            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
Beispiel #6
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            var pointValues = new long[] { 250, 500, 750, 1000 };

            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Adjust report criteria as needed
            if (criterion.StartDate == null)
            {
                criterion.StartDate = DateTime.MinValue;
            }
            if (criterion.EndDate == null)
            {
                criterion.EndDate = DateTime.MaxValue;
            }
            #endregion Adjust report criteria as needed

            #region Collect data
            UpdateProgress(progress, 1, "Getting total user count...", request.Name);

            var totalCheck = new Dictionary <long, long>();

            // header row
            var row = new List <object> {
                "System Name",
                "Branch Name",
                "Program",
                "Registered Users"
            };
            foreach (var pointValue in pointValues)
            {
                row.Add($"Achieved {pointValue} points");
                totalCheck.Add(pointValue, 0);
            }
            report.HeaderRow = row.ToArray();

            long totalRegistered = 0;
            long count           = 0;

            var programIds = await _programRepository.GetAllAsync((int)criterion.SiteId);

            long reportUserCount = 0;

            var branches = criterion.SystemId != null
                ? await _branchRepository.GetBySystemAsync((int)criterion.SystemId)
                : await _branchRepository.GetAllAsync((int)criterion.SiteId);

            var systemIds = branches
                            .OrderBy(_ => _.SystemName)
                            .GroupBy(_ => _.SystemId)
                            .Select(_ => _.First().SystemId);

            foreach (var systemId in systemIds)
            {
                var userCriterion = new ReportCriterion
                {
                    SiteId   = criterion.SiteId,
                    SystemId = systemId
                };
                reportUserCount += await _userRepository.GetCountAsync(userCriterion);
            }

            UpdateProgress(progress,
                           $"Beginning processing of {reportUserCount} users...",
                           request.Name);

            foreach (var systemId in systemIds)
            {
                foreach (var branch in branches.Where(_ => _.SystemId == systemId))
                {
                    foreach (var program in programIds)
                    {
                        if (token.IsCancellationRequested)
                        {
                            break;
                        }

                        string processing = systemIds.Count() == 1
                            ? $"Processing: {branch.Name} - {program.Name} -"
                            : $"Processing: {branch.SystemName} - {branch.Name} -";

                        // clear counters of participants that achieved point values
                        var programCheck = new Dictionary <long, long>();
                        foreach (var pointValue in pointValues)
                        {
                            programCheck.Add(pointValue, 0);
                        }

                        // get users for this program, branch, system
                        criterion.ProgramId = program.Id;
                        criterion.BranchId  = branch.Id;
                        criterion.SystemId  = systemId;

                        var userIds = await _userRepository
                                      .GetUserIdsByBranchProgram(criterion);

                        foreach (var userId in userIds)
                        {
                            if (++count % 10 == 0)
                            {
                                UpdateProgress(progress,
                                               Math.Max((int)((count * 100) / reportUserCount), 1),
                                               $"{processing} {count}/{reportUserCount}",
                                               request.Name);
                            }
                            var pointsUntilPeriod = await _userLogRepository
                                                    .GetEarningsUpToDateAsync(userId,
                                                                              criterion.StartDate ?? DateTime.MinValue);

                            var pointsDuringPeriod = await _userLogRepository
                                                     .GetEarningsOverPeriodAsync(userId, criterion);

                            var pointsUntilPeriodEnd = pointsUntilPeriod + pointsDuringPeriod;

                            foreach (var pointValue in pointValues)
                            {
                                if (pointsUntilPeriod < pointValue &&
                                    pointValue <= pointsUntilPeriodEnd)
                                {
                                    programCheck[pointValue] += 1;
                                }
                            }
                        }

                        int userCount = await _userRepository.GetCountAsync(criterion);

                        // add row
                        row = new List <object> {
                            branch.SystemName,
                            branch.Name,
                            program.Name,
                            userCount
                        };
                        foreach (var pointValue in pointValues)
                        {
                            row.Add(programCheck[pointValue]);
                            totalCheck[pointValue] += programCheck[pointValue];
                        }
                        reportData.Add(row.ToArray());

                        totalRegistered += userCount;
                    }

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                }
                if (token.IsCancellationRequested)
                {
                    break;
                }
            }

            report.Data = reportData.ToArray();

            // total row
            row = new List <object>
            {
                "Total",
                string.Empty,
                string.Empty,
                totalRegistered
            };
            foreach (var pointValue in pointValues)
            {
                row.Add(totalCheck[pointValue]);
            }
            report.FooterRow = row.ToArray();
            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
Beispiel #7
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Adjust report criteria as needed
            IEnumerable <int> badgeIds     = null;
            IEnumerable <int> challengeIds = null;

            if (!string.IsNullOrEmpty(criterion.BadgeRequiredList))
            {
                try
                {
                    badgeIds = criterion.BadgeRequiredList.Split(',').Select(int.Parse);
                }
                catch (Exception ex)
                {
                    _logger.LogError($"Unable to convert badge id list to numbers: {ex.Message}");
                    _logger.LogError($"Badge id list: {criterion.BadgeRequiredList}");
                }
            }

            if (!string.IsNullOrEmpty(criterion.ChallengeRequiredList))
            {
                try
                {
                    challengeIds = criterion.ChallengeRequiredList.Split(',').Select(int.Parse);
                }
                catch (Exception ex)
                {
                    _logger.LogError($"Unable to convert challenge id list to numbers: {ex.Message}");
                    _logger.LogError($"Challenge id list: {criterion.BadgeRequiredList}");
                }
            }

            if (criterion.StartDate == null)
            {
                criterion.StartDate = DateTime.MinValue;
            }

            if (criterion.EndDate == null)
            {
                criterion.EndDate = DateTime.MaxValue;
            }

            #endregion Adjust report criteria as needed

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Rank",
                "Participant",
                "System Name",
                "Branch Name",
                "Program",
                "Points Earned"
            };

            ICollection <int> usersWhoEarned = null;

            if (badgeIds != null && !token.IsCancellationRequested)
            {
                UpdateProgress(progress, 1, "Looking up users who earned badges...", request.Name);

                foreach (var badgeId in badgeIds)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    var earned = await _userLogRepository.UserIdsEarnedBadgeAsync(badgeId, criterion);

                    usersWhoEarned = earned;
                }
            }

            if (challengeIds != null && !token.IsCancellationRequested)
            {
                UpdateProgress(progress, 1, "Looking up users who completed challenges...", request.Name);

                foreach (var challengeId in challengeIds)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    var earned
                        = await _userLogRepository.UserIdsCompletedChallengesAsync(challengeId, criterion);

                    if (usersWhoEarned == null || usersWhoEarned.Count == 0)
                    {
                        usersWhoEarned = earned;
                    }
                    else
                    {
                        usersWhoEarned = usersWhoEarned.Union(earned).ToList();
                    }
                }
            }

            int  totalCount  = usersWhoEarned.Count;
            int  count       = 0;
            long totalPoints = 0;

            foreach (int userId in usersWhoEarned)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                UpdateProgress(progress,
                               ++count * 100 / usersWhoEarned.Count(),
                               $"Processing user: {count}/{usersWhoEarned.Count()}",
                               request.Name);

                long pointsEarned = await _userLogRepository.GetEarningsOverPeriodAsync(userId, criterion);

                var user = await _userRepository.GetByIdAsync(userId);

                var name = new StringBuilder(user.FirstName);
                if (!string.IsNullOrEmpty(user.LastName))
                {
                    name.Append($" {user.LastName}");
                }
                if (!string.IsNullOrEmpty(user.Username))
                {
                    name.Append($" ({user.Username})");
                }

                reportData.Add(new object[]
                {
                    0,
                    name.ToString(),
                    user.SystemName,
                    user.BranchName,
                    user.ProgramName,
                    pointsEarned
                });

                totalPoints += pointsEarned;
            }

            int rank = 1;
            report.Data = reportData
                          .OrderByDescending(_ => _.ElementAt(5))
                          .Select(_ => new object[] {
                rank++,
                _.ElementAt(1),
                _.ElementAt(2),
                _.ElementAt(3),
                _.ElementAt(4),
                _.ElementAt(5),
            });

            report.FooterRow = new object[]
            {
                "Total",
                string.Empty,
                string.Empty,
                string.Empty,
                string.Empty,
                totalPoints
            };
            report.AsOf = _serviceFacade.DateTimeProvider.Now;
            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
        public async override Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion = await GetCriterionAsync(request);

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };

            var reportData = new List <object[]>();


            var askIfFirstTime
                = await GetSiteSettingBoolAsync(criterion, SiteSettingKey.Users.AskIfFirstTime);

            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object>()
            {
                "System Name",
                "Branch Name",
                "Program Name",
                "Registered Users",
            };

            if (askIfFirstTime)
            {
                headerRow.Add("First time Participants");
            }

            var translations      = new Dictionary <string, ICollection <int?> >();
            var translationTotals = new Dictionary <string, long>();

            var programDictionary = (await _programRepository.GetAllAsync((int)criterion.SiteId))
                                    .ToDictionary(_ => _.Id, _ => _.Name);

            foreach (var programId in programDictionary.Keys)
            {
                var pointTranslation = await _pointTranslationRepository
                                       .GetByProgramIdAsync(programId);

                string description = pointTranslation.ActivityDescriptionPlural;

                if (!translations.ContainsKey(description))
                {
                    translations.Add(description, new List <int?> {
                        pointTranslation.Id
                    });
                    translationTotals.Add(description, 0);
                    if (description.Length > 2)
                    {
                        headerRow.Add(description.First().ToString().ToUpper()
                                      + description.Substring(1));
                    }
                    else
                    {
                        headerRow.Add(description);
                    }
                }
                else
                {
                    translations[description].Add(pointTranslation.Id);
                }
            }
            report.HeaderRow = headerRow.ToArray();

            int count = 0;

            // running totals
            long totalRegistered = 0;
            long totalFirstTime  = 0;

            var branches = criterion.SystemId != null
                ? await _branchRepository.GetBySystemAsync((int)criterion.SystemId)
                : await _branchRepository.GetAllAsync((int)criterion.SiteId);

            var systemIds = branches
                            .OrderBy(_ => _.SystemName)
                            .GroupBy(_ => _.SystemId)
                            .Select(_ => _.First().SystemId);

            int totalItems = branches.Count() * programDictionary.Count();

            foreach (var systemId in systemIds)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                foreach (var branch in branches.Where(_ => _.SystemId == systemId))
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    foreach (var programId in programDictionary.Keys)
                    {
                        UpdateProgress(progress,
                                       ++count * 100 / totalItems,
                                       $"Processing: {branch.SystemName} - {branch.Name}",
                                       request.Name);

                        criterion.SystemId  = systemId;
                        criterion.BranchId  = branch.Id;
                        criterion.ProgramId = programId;

                        int users = await _userRepository.GetCountAsync(criterion);

                        totalRegistered += users;

                        var row = new List <object>()
                        {
                            branch.SystemName,
                            branch.Name,
                            programDictionary[programId],
                            users
                        };

                        if (askIfFirstTime)
                        {
                            int firstTime = await _userRepository.GetFirstTimeCountAsync(criterion);

                            totalFirstTime += firstTime;

                            row.Add(firstTime);
                        }

                        foreach (var translationName in translations.Keys)
                        {
                            long total = await _userLogRepository.TranslationEarningsAsync(criterion,
                                                                                           translations[translationName]);

                            row.Add(total);
                            translationTotals[translationName] += total;
                        }

                        reportData.Add(row.ToArray());

                        if (token.IsCancellationRequested)
                        {
                            break;
                        }
                    }
                }
            }

            report.Data = reportData.ToArray();

            // total row
            var footerRow = new List <object>()
            {
                "Total",
                string.Empty,
                string.Empty,
                totalRegistered,
            };

            if (askIfFirstTime)
            {
                footerRow.Add(totalFirstTime);
            }

            foreach (var total in translationTotals.Values)
            {
                footerRow.Add(total);
            }

            report.FooterRow = footerRow.ToArray();
            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
Beispiel #9
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            string title = "";

            if (criterion.BranchId.HasValue)
            {
                criterion.SystemId = null;
                title = (await _branchRepository.GetByIdAsync(criterion.BranchId.Value)).Name;
            }
            else if (criterion.SystemId.HasValue)
            {
                title = (await _systemRepository.GetByIdAsync(criterion.SystemId.Value)).Name;
            }
            else
            {
                throw new GraException("No system or branch selected.");
            }

            var report = new StoredReport
            {
                Title = title,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Prize Name",
                "# Redeemed"
            };

            int count = 0;

            var prizes = await _prizeWinnerRepository.GetRedemptionsAsync(criterion);

            foreach (var prize in prizes
                     .Where(_ => string.IsNullOrEmpty(_.PrizeName) &&
                            _.DrawingId == null &&
                            _.TriggerId == null))
            {
                prize.PrizeName = "Free Book";
            }

            var prizeGroups = prizes.GroupBy(_ => new
            {
                _.PrizeName,
                _.DrawingId,
                _.TriggerId
            })
                              .Select(_ => new
            {
                Prize = _.Key,
                Count = _.Count()
            })
                              .OrderBy(_ => _.Prize.PrizeName);

            int prizeGroupsCount = prizeGroups.Count();

            foreach (var group in prizeGroups)
            {
                UpdateProgress(progress,
                               ++count * 100 / prizeGroupsCount,
                               $"Processing: {count}/{prizeGroupsCount}",
                               request.Name);

                if (token.IsCancellationRequested)
                {
                    break;
                }

                reportData.Add(new object[] {
                    group.Prize.PrizeName,
                    group.Count
                });
            }

            report.Data = reportData.ToArray();
            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
Beispiel #10
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };

            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Adjust report criteria as needed
            IEnumerable <int> triggerIds = null;

            if (!string.IsNullOrEmpty(criterion.TriggerList))
            {
                try
                {
                    triggerIds = criterion.TriggerList.Split(',').Select(int.Parse);
                }
                catch (Exception ex)
                {
                    _logger.LogError($"Unable to convert trigger id list to numbers: {ex.Message}");
                    _logger.LogError($"Badge id list: {criterion.TriggerList}");
                }
            }
            else
            {
                throw new GraException("No prizes selected.");
            }
            #endregion Adjust report criteria as needed

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                criterion.SystemId.HasValue ? "Branch Name" : "System Name",
                "# Redeemed"
            };

            int count = 0;
            int totalRedemptionCount = 0;
            if (criterion.SystemId.HasValue)
            {
                var branches = await _branchRepository.GetBySystemAsync(criterion.SystemId.Value);

                foreach (var branch in branches)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    UpdateProgress(progress,
                                   ++count * 100 / branches.Count(),
                                   $"Processing: {branch.SystemName} - {branch.Name}",
                                   request.Name);

                    var redemptionCount = await _prizeWinnerRepository
                                          .GetBranchPrizeRedemptionCountAsync(branch.Id, triggerIds);

                    totalRedemptionCount += redemptionCount;

                    IEnumerable <object> row = new object[]
                    {
                        branch.Name,
                        redemptionCount
                    };
                    reportData.Add(row.ToArray());
                }
            }
            else
            {
                var systems = await _systemRepository.GetAllAsync(criterion.SiteId.Value);

                foreach (var system in systems)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    UpdateProgress(progress,
                                   ++count * 100 / systems.Count(),
                                   $"Processing: {system.Name}",
                                   request.Name);

                    var redemptionCount = await _prizeWinnerRepository
                                          .GetSystemPrizeRedemptionCountAsync(system.Id, triggerIds);

                    totalRedemptionCount += redemptionCount;

                    IEnumerable <object> row = new object[]
                    {
                        system.Name,
                        redemptionCount
                    };
                    reportData.Add(row.ToArray());
                }
            }

            report.Data = reportData.ToArray();

            IEnumerable <object> footerRow = new object[]
            {
                "Total",
                totalRedemptionCount
            };
            report.FooterRow = footerRow.ToArray();

            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            var groupInfo = await _groupInfoRepository.GetByIdAsync(criterion.GroupInfoId.Value);

            string title = groupInfo.Name;

            var report = new StoredReport
            {
                Title = title,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Name",
                "Vendor Code",
            };

            var head = await _userRepository.GetByIdAsync(groupInfo.UserId);

            var users = await _userRepository.GetHouseholdAsync(groupInfo.UserId);

            users = users.Prepend(head);

            foreach (var user in users)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                var vendorCode = await _vendorCodeRepository.GetUserVendorCode(user.Id);

                var row = new List <object> {
                    user.FullName,
                    vendorCode?.IsDonated == false ? vendorCode.Code : ""
                };

                reportData.Add(row.ToArray());
            }

            report.Data = reportData.ToArray();

            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object>()
            {
                "Community experience",
                "Participants"
            };

            report.HeaderRow = headerRow.ToArray();

            // running totals
            long totalParticipants = 0;

            var communityExperiencesWithCount = await _eventRepository
                                                .GetCommunityExperienceAttendanceAsync(criterion);

            foreach (var communityExperienceWithCount in communityExperiencesWithCount)
            {
                var row = new List <object>()
                {
                    communityExperienceWithCount.Data.Name,
                    communityExperienceWithCount.Count
                };

                totalParticipants += communityExperienceWithCount.Count;

                reportData.Add(row.ToArray());
            }

            report.Data = reportData.ToArray();

            // total row
            var footerRow = new List <object>()
            {
                "Total",
                totalParticipants
            };

            report.FooterRow = footerRow.ToArray();
            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
Beispiel #13
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();

            var askIfFirstTime
                = await GetSiteSettingBoolAsync(criterion, SiteSettingKey.Users.AskIfFirstTime);

            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object> {
                "System Name",
                "Branch Name",
                "Registered Users"
            };

            if (askIfFirstTime)
            {
                headerRow.Add("First time Participants");
            }

            headerRow.Add("Achievers");
            headerRow.Add("Challenges Completed");
            headerRow.Add("Badges Earned");

            var translations      = new Dictionary <string, ICollection <int?> >();
            var translationTotals = new Dictionary <string, long>();

            foreach (var program in await _programRepository.GetAllAsync((int)criterion.SiteId))
            {
                var pointTranslation = await _pointTranslationRepository
                                       .GetByProgramIdAsync(program.Id);

                string description = pointTranslation.ActivityDescriptionPlural;

                if (!translations.ContainsKey(description))
                {
                    translations.Add(description, new List <int?> {
                        pointTranslation.Id
                    });
                    translationTotals.Add(description, 0);
                    if (description.Length > 2)
                    {
                        headerRow.Add(description[0]
                                      .ToString()
                                      .ToUpper(CultureInfo.InvariantCulture)
                                      + description[1..]);
Beispiel #14
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository
                  .GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            string title = "";

            if (criterion.SystemId.HasValue)
            {
                title = (await _systemRepository.GetByIdAsync(criterion.SystemId.Value)).Name;
            }

            var report = new StoredReport
            {
                Title = title,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();

            #endregion Reporting initialization

            #region Collect data

            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                criterion.SystemId.HasValue ? "Branch Name" : "System Name"
            };

            var programs = await _programRepository.GetAllAsync(criterion.SiteId.Value);

            foreach (var program in programs)
            {
                report.HeaderRow = report.HeaderRow.Append(program.Name);
            }

            report.HeaderRow = report.HeaderRow.Append("Total");

            int count = 0;

            var users = await _userRepository.GetUsersByCriterionAsync(criterion);

            if (criterion.SystemId.HasValue)
            {
                users = users.Where(_ => _.SystemId == criterion.SystemId);
                var branches = await _branchRepository.GetBySystemAsync(criterion.SystemId.Value);

                foreach (var branch in branches)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    UpdateProgress(progress,
                                   ++count * 100 / branches.Count(),
                                   $"Processing: {branch.SystemName} - {branch.Name}",
                                   request.Name);

                    var branchUsers          = users.Where(_ => _.BranchId == branch.Id);
                    IEnumerable <object> row = new object[]
                    {
                        branch.Name
                    };
                    foreach (var program in programs)
                    {
                        row = row.Append(branchUsers.Count(_ => _.ProgramId == program.Id));
                    }
                    row = row.Append(branchUsers.Count());
                    reportData.Add(row.ToArray());
                }
            }
            else
            {
                var systems = await _systemRepository.GetAllAsync(criterion.SiteId.Value);

                foreach (var system in systems)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    UpdateProgress(progress,
                                   ++count * 100 / systems.Count(),
                                   $"Processing: {system.Name}",
                                   request.Name);

                    var systemUsers          = users.Where(_ => _.SystemId == system.Id);
                    IEnumerable <object> row = new object[]
                    {
                        system.Name
                    };
                    foreach (var program in programs)
                    {
                        row = row.Append(systemUsers.Count(_ => _.ProgramId == program.Id));
                    }
                    row = row.Append(systemUsers.Count());
                    reportData.Add(row.ToArray());
                }
            }

            report.Data = reportData.ToArray();

            IEnumerable <object> footerRow = new object[]
            {
                "Total"
            };
            foreach (var program in programs)
            {
                footerRow = footerRow.Append(users.Count(_ => _.ProgramId == program.Id));
            }
            footerRow = footerRow.Append(users.Count());

            report.FooterRow = footerRow.ToArray();

            #endregion Collect data

            #region Finish up reporting

            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[]
            {
                "School Name",
                "School Type",
                "Registered Users",
                "Achievers"
            };

            int count = 0;

            // running totals
            long totalRegistered = 0;
            long totalAchiever   = 0;

            ICollection <School> schools = null;

            if (criterion.SchoolId != null)
            {
                schools = new List <School>()
                {
                    await _schoolRepository.GetByIdAsync((int)criterion.SchoolId)
                };
            }
            else if (criterion.SchoolDistrictId != null)
            {
                schools = await _schoolRepository.GetAllAsync((int)criterion.SiteId,
                                                              criterion.SchoolDistrictId);
            }

            if (schools == null)
            {
                throw new Exception("Could not find any school(s) to report on.");
            }

            foreach (var school in schools)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                UpdateProgress(progress,
                               ++count * 100 / schools.Count(),
                               $"Processing: {school.Name}",
                               request.Name);

                criterion.SchoolDistrictId = null;
                criterion.SchoolId         = school.Id;

                int users = await _userRepository.GetCountAsync(criterion);

                int achievers = await _userRepository.GetAchieverCountAsync(criterion);

                totalRegistered += users;
                totalAchiever   += achievers;

                string schoolTypeName = null;
                if (school.SchoolTypeId.HasValue)
                {
                    var schoolType = await _schoolTypeRepository
                                     .GetByIdAsync(school.SchoolTypeId.Value);

                    schoolTypeName = schoolType.Name;
                }


                // add row
                reportData.Add(new object[] {
                    school.Name,
                    schoolTypeName,
                    users,
                    achievers
                });
            }

            report.Data = reportData.ToArray();

            // total row
            report.FooterRow = new object[]
            {
                "Total",
                string.Empty,
                totalRegistered,
                totalAchiever
            };

            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
Beispiel #16
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object> {
                "Community experience",
                "Participants"
            };

            report.HeaderRow = headerRow.ToArray();

            // running totals
            long totalParticipants = 0;

            UpdateProgress(progress, 1, "Looking up community experiences...");

            var communityExperiencesWithCount = await _eventRepository
                                                .GetCommunityExperienceAttendanceAsync(criterion);

            int onRow = 0;

            foreach (var communityExperienceWithCount in communityExperiencesWithCount)
            {
                if (onRow % 10 == 0)
                {
                    UpdateProgress(progress,
                                   ++onRow * 100 / Math.Max(communityExperiencesWithCount.Count, 1),
                                   $"Tabulating {communityExperienceWithCount.Data.Name}...");
                }

                var row = new List <object>
                {
                    communityExperienceWithCount.Data.Name,
                    communityExperienceWithCount.Count
                };

                totalParticipants += communityExperienceWithCount.Count;

                reportData.Add(row.ToArray());
            }

            report.Data = reportData.ToArray();

            // total row
            var footerRow = new List <object>
            {
                "Total",
                totalParticipants
            };

            report.FooterRow = footerRow.ToArray();
            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting intialization

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository
                  .GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (!criterion.SiteId.HasValue)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            if (!criterion.BranchId.HasValue)
            {
                throw new ArgumentException(nameof(criterion.BranchId));
            }

            var branch = await _branchRepository.GetByIdAsync(criterion.BranchId.Value);

            var report = new StoredReport
            {
                Title = branch.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();

            #endregion Reporting intialization

            #region Collect data

            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[]
            {
                "Name",
                "Email",
                "Phone",
                "Item name",
                "Item arrival",
                "Email sent"
            };

            int count = 0;

            var remainingPrizes = await _vendorCodeRepository
                                  .GetRemainingPrizesForBranchAsync(criterion.BranchId.Value);

            foreach (var prize in remainingPrizes)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                UpdateProgress(progress,
                               ++count * 100 / remainingPrizes.Count,
                               $"Processing: {branch.Name}",
                               request.Name);

                var user = await _userRepository.GetByIdAsync(prize.UserId.Value);

                var name = new StringBuilder(user.FirstName);
                if (!string.IsNullOrEmpty(user.LastName))
                {
                    name.Append(' ').Append(user.LastName);
                }
                if (!string.IsNullOrEmpty(user.Username))
                {
                    name.Append(" (").Append(user.Username).Append(')');
                }

                reportData.Add(new object[]
                {
                    name.ToString(),
                    user.Email,
                    user.PhoneNumber,
                    prize.Details,
                    prize.ArrivalDate.HasValue
                        ? prize.ArrivalDate.Value.ToString("g", CultureInfo.CurrentCulture)
                        : null,
                    prize.EmailSentAt.HasValue
                        ? prize.EmailSentAt.Value.ToString("g", CultureInfo.CurrentCulture)
                        : null
                });
            }

            report.Data = reportData.ToArray();

            #endregion Collect data

            #region Finish up reporting

            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            int count = 0;
            var asof  = _serviceFacade.DateTimeProvider.Now;

            var askIfFirstTime
                = await GetSiteSettingBoolAsync(criterion, SiteSettingKey.Users.AskIfFirstTime);

            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            var programTotals = new Dictionary <int, (int users, int firstTime, int achievers)>();

            var programReports = new List <StoredReport>();

            var programs = await _programRepository.GetAllAsync((int)criterion.SiteId);

            var branches = await _branchRepository.GetAllAsync((int)criterion.SiteId);

            int totalItems = branches.Count() * programs.Count();

            foreach (var program in programs)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                var report = new StoredReport
                {
                    Title = program.Name,
                    AsOf  = asof
                };
                var reportData = new List <object[]>();

                // header row
                var headerRow = new List <object> {
                    "Library System",
                    "Library",
                    "Signups"
                };

                if (askIfFirstTime)
                {
                    headerRow.Add("First time Participants");
                }

                headerRow.Add("Achievers");

                report.HeaderRow = headerRow.ToArray();

                int programTotalUsers     = 0;
                int programTotalFirstTime = 0;
                int programTotalAchievers = 0;

                var systemIds = branches
                                .OrderBy(_ => _.SystemName)
                                .GroupBy(_ => _.SystemId)
                                .Select(_ => _.First().SystemId);
                foreach (var systemId in systemIds)
                {
                    foreach (var branch in branches.Where(_ => _.SystemId == systemId))
                    {
                        if (totalItems > 0)
                        {
                            UpdateProgress(progress,
                                           ++count * 100 / totalItems,
                                           $"{program.Name} - {branch.SystemName}",
                                           request.Name);
                        }

                        criterion.BranchId  = branch.Id;
                        criterion.ProgramId = program.Id;

                        int users = await _userRepository.GetCountAsync(criterion);

                        int achievers = await _userRepository.GetAchieverCountAsync(criterion);

                        var row = new List <object> {
                            branch.SystemName,
                            branch.Name,
                            users
                        };

                        if (askIfFirstTime)
                        {
                            int firstTime = await _userRepository.GetFirstTimeCountAsync(criterion);

                            programTotalFirstTime += firstTime;

                            row.Add(firstTime);
                        }

                        row.Add(achievers);

                        programTotalUsers     += users;
                        programTotalAchievers += achievers;

                        reportData.Add(row.ToArray());

                        if (token.IsCancellationRequested)
                        {
                            break;
                        }
                    } // foreach branch

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                } // foreach system

                report.Data = reportData.ToArray();

                var footerRow = new List <object>
                {
                    "Total",
                    string.Empty,
                    programTotalUsers,
                };

                if (askIfFirstTime)
                {
                    footerRow.Add(programTotalFirstTime);
                }

                footerRow.Add(programTotalAchievers);

                report.FooterRow = footerRow.ToArray();

                programTotals.Add(program.Id, (programTotalUsers, programTotalFirstTime, programTotalAchievers));

                double completion = 0;
                if (programTotalUsers > 0)
                {
                    completion = (double)programTotalAchievers * 100 / programTotalUsers;
                }

                var endDate = criterion.EndDate ?? asof;

                report.FooterText = new string[]
                {
                    $"Completion rate: {completion:N2}%",
                    $"This report was run on {asof:g} and contains data up to {endDate:g}."
                };

                programReports.Add(report);
            } // foreach program

            var summaryReport = new StoredReport
            {
                Title = "Summary",
                AsOf  = asof
            };
            var summaryReportData = new List <object[]>();

            var summaryHeader = new List <object>()
            {
                "Program",
                "Signups",
            };

            if (askIfFirstTime)
            {
                summaryHeader.Add("First time Participants");
            }

            summaryHeader.Add("Achievers");
            summaryHeader.Add("Achiever Points");

            summaryReport.HeaderRow = summaryHeader.ToArray();

            int signupTotal    = 0;
            int firstTimeTotal = 0;
            int achieverTotal  = 0;

            foreach (var program in programs)
            {
                var(users, firstTime, achievers) = programTotals[program.Id];

                var summaryRow = new List <object>
                {
                    program.Name,
                    users
                };

                if (askIfFirstTime)
                {
                    summaryRow.Add(firstTime);
                }

                summaryRow.Add(achievers);
                summaryRow.Add(program.AchieverPointAmount);

                summaryReportData.Add(summaryRow.ToArray());

                signupTotal    += users;
                firstTimeTotal += firstTime;
                achieverTotal  += achievers;
            }

            summaryReport.Data = summaryReportData.ToArray();

            var summaryFooter = new List <object>()
            {
                "Total",
                signupTotal,
            };

            if (askIfFirstTime)
            {
                summaryFooter.Add(firstTimeTotal);
            }

            summaryFooter.Add(achieverTotal);
            summaryFooter.Add(string.Empty);

            summaryReport.FooterRow = summaryFooter.ToArray();

            double totalCompletion = 0;
            if (signupTotal > 0)
            {
                totalCompletion = (double)achieverTotal * 100 / signupTotal;
            }

            summaryReport.FooterText = new string[] {
                $"Completion rate: {totalCompletion:N2}%"
            };
            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(summaryReport);
                foreach (var report in programReports)
                {
                    ReportSet.Reports.Add(report);
                }
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            string title = "";

            if (criterion.SystemId.HasValue)
            {
                title = (await _systemRepository.GetByIdAsync(criterion.SystemId.Value)).Name;
            }

            var report = new StoredReport
            {
                Title = title,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();

            var askIfFirstTime
                = await GetSiteSettingBoolAsync(criterion, SiteSettingKey.Users.AskIfFirstTime);

            var reportEmailAwardData
                = await _vendorCodeTypeRepository.SiteHasEmailAwards(criterion.SiteId.Value);

            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object>
            {
                "System Name",
                "Branch Name"
            };

            // first time?

            if (askIfFirstTime)
            {
                headerRow.Add("First Time # Earned");
                headerRow.Add("First Time # Ordered");
                if (reportEmailAwardData)
                {
                    headerRow.Add("First Time # Email Awarded");
                }
            }

            headerRow.Add("# Earned");
            headerRow.Add("# Ordered");
            if (reportEmailAwardData)
            {
                headerRow.Add("# Email Awarded");
            }

            report.HeaderRow = headerRow.ToArray();

            int count = 0;

            // running totals
            int totalEarned       = 0;
            int totalOrdered      = 0;
            int totalEmailAwarded = 0;

            int totalFirstEarned       = 0;
            int totalFirstOrdered      = 0;
            int totalFirstEmailAwarded = 0;

            var branches = criterion.SystemId != null
                ? await _branchRepository.GetBySystemAsync((int)criterion.SystemId)
                : await _branchRepository.GetAllAsync((int)criterion.SiteId);

            var systemIds = branches
                            .OrderBy(_ => _.SystemName)
                            .GroupBy(_ => _.SystemId)
                            .Select(_ => _.First().SystemId);

            foreach (var systemId in systemIds)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                foreach (var branch in branches.Where(_ => _.SystemId == systemId))
                {
                    UpdateProgress(progress,
                                   ++count * 100 / branches.Count(),
                                   $"Processing: {branch.SystemName} - {branch.Name}",
                                   request.Name);

                    criterion.SystemId = systemId;
                    criterion.BranchId = branch.Id;

                    var row = new List <object> {
                        branch.SystemName,
                        branch.Name,
                    };

                    if (askIfFirstTime)
                    {
                        criterion.IsFirstTimeParticipant = true;
                        var firstVendorCodes =
                            await _vendorCodeRepository.GetEarnedCodesAsync(criterion);

                        int firstEarnedCodes = firstVendorCodes.Count;
                        int firstUsedCodes   = firstVendorCodes.Count(_ => _.IsUsed);

                        criterion.IsFirstTimeParticipant = false;

                        row.Add(firstEarnedCodes);
                        row.Add(firstUsedCodes);

                        totalFirstEarned  += firstEarnedCodes;
                        totalFirstOrdered += firstUsedCodes;

                        if (reportEmailAwardData)
                        {
                            int firstEmailAwardCodes = firstVendorCodes
                                                       .Count(_ => _.EmailAwardSent.HasValue);
                            row.Add(firstEmailAwardCodes);
                            totalFirstEmailAwarded += firstEmailAwardCodes;
                        }
                    }

                    var vendorCodes = await _vendorCodeRepository.GetEarnedCodesAsync(criterion);

                    int earnedCodes = vendorCodes.Count;
                    int usedCodes   = vendorCodes.Count(_ => _.IsUsed);

                    totalEarned  += earnedCodes;
                    totalOrdered += usedCodes;

                    row.Add(earnedCodes);
                    row.Add(usedCodes);

                    if (reportEmailAwardData)
                    {
                        int emailAwardCodes = vendorCodes
                                              .Count(_ => _.EmailAwardSent.HasValue);
                        totalEmailAwarded += emailAwardCodes;
                        row.Add(emailAwardCodes);
                    }

                    reportData.Add(row.ToArray());

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }

            report.Data = reportData.ToArray();

            // total row
            var footerRow = new List <object>
            {
                "Total",
                string.Empty
            };

            if (askIfFirstTime)
            {
                footerRow.Add(totalFirstEarned);
                footerRow.Add(totalFirstOrdered);
                if (reportEmailAwardData)
                {
                    footerRow.Add(totalFirstEmailAwarded);
                }
            }

            footerRow.Add(totalEarned);
            footerRow.Add(totalOrdered);
            if (reportEmailAwardData)
            {
                footerRow.Add(totalEmailAwarded);
            }

            report.FooterRow = footerRow.ToArray();

            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
Beispiel #20
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            string title = "";

            if (criterion.SystemId.HasValue)
            {
                title = (await _systemRepository.GetByIdAsync(criterion.SystemId.Value)).Name;
            }

            var report = new StoredReport
            {
                Title = title,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "System Name",
                "Branch Name",
                "# Earned",
                "# Ordered"
            };

            int count = 0;

            // running totals
            int totalEarned  = 0;
            int totalOrdered = 0;

            var branches = criterion.SystemId != null
                ? await _branchRepository.GetBySystemAsync((int)criterion.SystemId)
                : await _branchRepository.GetAllAsync((int)criterion.SiteId);

            var systemIds = branches
                            .OrderBy(_ => _.SystemName)
                            .GroupBy(_ => _.SystemId)
                            .Select(_ => _.First().SystemId);

            foreach (var systemId in systemIds)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                foreach (var branch in branches.Where(_ => _.SystemId == systemId))
                {
                    UpdateProgress(progress,
                                   ++count * 100 / branches.Count(),
                                   $"Processing: {branch.SystemName} - {branch.Name}",
                                   request.Name);

                    criterion.SystemId = systemId;
                    criterion.BranchId = branch.Id;

                    var vendorCodes = await _vendorCodeRepository.GetEarnedCodesAsync(criterion);

                    int earnedCodes = vendorCodes.Count;
                    int usedCodes   = vendorCodes.Where(_ => _.IsUsed).Count();

                    totalEarned  += earnedCodes;
                    totalOrdered += usedCodes;

                    var row = new List <object>()
                    {
                        branch.SystemName,
                        branch.Name,
                        earnedCodes,
                        usedCodes
                    };

                    reportData.Add(row.ToArray());

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }

            report.Data = reportData.ToArray();

            // total row
            var footerRow = new List <object>()
            {
                "Total",
                string.Empty,
                totalEarned,
                totalOrdered
            };

            report.FooterRow = footerRow.ToArray();

            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
Beispiel #21
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Rank",
                "System Name",
                "Branch Name",
                "Program",
                "Participant",
                "Points Earned"
            };

            int count = 0;
            int total = TopToShow;

            IEnumerable <User> users = await _userRepository.GetTopScoresAsync(criterion, total);

            // TODO establish why this isn't sorting properly in production
            foreach (var user in users.OrderByDescending(_ => _.PointsEarned))
            {
                UpdateProgress(progress,
                               ++count * 100 / users.Count(),
                               $"Processing: {count}/{users.Count()}",
                               request.Name);

                if (token.IsCancellationRequested)
                {
                    break;
                }

                var name = new StringBuilder(user.FirstName);
                if (!string.IsNullOrEmpty(user.LastName))
                {
                    name.Append($" {user.LastName}");
                }
                if (!string.IsNullOrEmpty(user.Username))
                {
                    name.Append($" ({user.Username})");
                }

                reportData.Add(new object[] {
                    count,
                    user.SystemName,
                    user.BranchName,
                    user.ProgramName,
                    name.ToString(),
                    user.PointsEarned
                });
            }

            report.Data = reportData.ToArray();
            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
Beispiel #22
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            var groupInfo = await _groupInfoRepository.GetByIdAsync(criterion.GroupInfoId.Value);

            string title = groupInfo.Name;

            var report = new StoredReport
            {
                Title = title,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Name",
                "Age",
                "Vendor Code",
            };

            var head = await _userRepository.GetByIdAsync(groupInfo.UserId);

            var users = await _userRepository.GetHouseholdAsync(groupInfo.UserId);

            users = users.Prepend(head);

            foreach (var user in users)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                var vendorCode = await _vendorCodeRepository.GetUserVendorCode(user.Id);

                var row = new List <object> {
                    user.FullName,
                    user.Age,
                    vendorCode?.IsDonated == false ? vendorCode.Code : ""
                };

                reportData.Add(row.ToArray());
            }

            report.Data = reportData.ToArray();

            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (!criterion.SiteId.HasValue)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            int count = 0;
            var asof  = _serviceFacade.DateTimeProvider.Now;

            #endregion Reporting initialization

            #region Collect data

            UpdateProgress(progress, 1, "Starting report...", request.Name);

            var programTotals = new Dictionary <int, (int earned, int donated, int redeemed)>();

            var programReports = new List <StoredReport>();

            var programs = await _programRepository.GetAllAsync((int)criterion.SiteId);

            int totalItems;

            IEnumerable <Model.System> systems  = null;
            IEnumerable <Branch>       branches = null;

            if (criterion.SystemId.HasValue)
            {
                branches = await _branchRepository.GetBySystemAsync(criterion.SystemId.Value);

                totalItems = programs.Count() * branches.Count();
            }
            else
            {
                systems = await _systemRepository.GetAllAsync(criterion.SiteId.Value);

                totalItems = programs.Count() * systems.Count();
            }

            foreach (var program in programs)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                var report = new StoredReport
                {
                    Title = program.Name,
                    AsOf  = asof
                };
                var reportData = new List <object[]>();

                criterion.ProgramId = program.Id;

                // header row
                var headerRow = new object[] {
                    "Earned",
                    "Donated",
                    "Redeemed"
                };

                int programTotalEarned   = 0;
                int programTotalDonated  = 0;
                int programTotalRedeened = 0;

                if (branches != null)
                {
                    headerRow = headerRow.Prepend("Branch Name").ToArray();

                    foreach (var branch in branches)
                    {
                        if (totalItems > 0)
                        {
                            UpdateProgress(progress,
                                           ++count * 100 / totalItems,
                                           $"{program.Name} - {branch.Name}",
                                           request.Name);
                        }

                        criterion.BranchId = branch.Id;

                        var vendorCodes = await _vendorCodeRepository
                                          .GetEarnedCodesAsync(criterion);

                        var earned   = vendorCodes.Count;
                        var donated  = vendorCodes.Count(_ => _.IsDonated == true);
                        var redeemed = vendorCodes.Count(_ => _.IsUsed);

                        programTotalEarned   += earned;
                        programTotalDonated  += donated;
                        programTotalRedeened += redeemed;

                        var row = new List <object>
                        {
                            branch.Name,
                            earned,
                            donated,
                            redeemed
                        };

                        reportData.Add(row.ToArray());

                        if (token.IsCancellationRequested)
                        {
                            break;
                        }
                    }
                } // foreach branch
                else
                {
                    headerRow = headerRow.Prepend("System Name").ToArray();

                    foreach (var system in systems)
                    {
                        if (totalItems > 0)
                        {
                            UpdateProgress(progress,
                                           ++count * 100 / totalItems,
                                           $"{program.Name} - {system.Name}",
                                           request.Name);
                        }

                        criterion.SystemId = system.Id;

                        var vendorCodes = await _vendorCodeRepository
                                          .GetEarnedCodesAsync(criterion);

                        var earned   = vendorCodes.Count;
                        var donated  = vendorCodes.Count(_ => _.IsDonated == true);
                        var redeemed = vendorCodes.Count(_ => _.IsUsed);

                        programTotalEarned   += earned;
                        programTotalDonated  += donated;
                        programTotalRedeened += redeemed;

                        var row = new List <object>
                        {
                            system.Name,
                            earned,
                            donated,
                            redeemed
                        };

                        reportData.Add(row.ToArray());

                        if (token.IsCancellationRequested)
                        {
                            break;
                        }
                    } // foreach system
                }     // foreach program

                report.HeaderRow = headerRow;
                report.Data      = reportData.ToArray();

                report.FooterRow = new object[]
                {
                    "Total",
                    programTotalEarned,
                    programTotalDonated,
                    programTotalRedeened
                };

                programTotals.Add(program.Id,
                                  (programTotalEarned, programTotalDonated, programTotalRedeened));

                programReports.Add(report);
            }

            var summaryReport = new StoredReport
            {
                Title = "Summary",
                AsOf  = asof
            };

            var summaryReportData = new List <object[]>();

            summaryReport.HeaderRow = new object[]
            {
                "Program",
                "# Earned",
                "# Donated",
                "# Redeemed"
            };

            int earnedTotal   = 0;
            int donatedTotal  = 0;
            int redeemedTotal = 0;

            foreach (var program in programs)
            {
                var(earned, donated, redeemed) = programTotals[program.Id];

                earnedTotal   += earned;
                donatedTotal  += donated;
                redeemedTotal += redeemed;

                summaryReportData.Add(new object[]
                {
                    program.Name,
                    earned,
                    donated,
                    redeemed
                });
            }

            summaryReport.Data = summaryReportData;

            summaryReport.FooterRow = new object[]
            {
                "Total",
                earnedTotal,
                donatedTotal,
                redeemedTotal
            };

            #endregion Collect data

            #region Finish up reporting

            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(summaryReport);
                foreach (var report in programReports)
                {
                    ReportSet.Reports.Add(report);
                }
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
Beispiel #24
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            string title = "";

            if (criterion.BranchId.HasValue)
            {
                criterion.SystemId = null;
                title = (await _branchRepository.GetByIdAsync(criterion.BranchId.Value)).Name;
            }
            else if (criterion.SystemId.HasValue)
            {
                title = (await _systemRepository.GetByIdAsync(criterion.SystemId.Value)).Name;
            }
            else
            {
                throw new GraException("No system or branch selected.");
            }

            var report = new StoredReport
            {
                Title = title,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Prize Name",
                "# Redeemed"
            };

            int count = 0;

            var prizes = await _prizeWinnterRepository.GetRedemptionsAsync(criterion);

            var prizeGroups = prizes.GroupBy(_ => new
            {
                PrizeName = _.PrizeName,
                DrawingId = _.DrawingId,
                TriggerId = _.TriggerId
            })
                              .Select(_ => new
            {
                Prize = _.Key,
                Count = _.Count()
            })
                              .OrderBy(_ => _.Prize.PrizeName);

            int prizeGroupsCount = prizeGroups.Count();

            foreach (var group in prizeGroups)
            {
                UpdateProgress(progress,
                               ++count * 100 / prizeGroupsCount,
                               $"Processing: {count}/{prizeGroupsCount}",
                               request.Name);

                if (token.IsCancellationRequested)
                {
                    break;
                }

                reportData.Add(new object[] {
                    group.Prize.PrizeName,
                    group.Count
                });
            }

            report.Data = reportData.ToArray();
            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
Beispiel #25
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            int count = 0;
            var asof  = _serviceFacade.DateTimeProvider.Now;
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            var programTotals = new Dictionary <int, (int users, int achievers)>();

            var programReports = new List <StoredReport>();

            var programs = await _programRepository.GetAllAsync((int)criterion.SiteId);

            var branches = await _branchRepository.GetAllAsync((int)criterion.SiteId);

            int totalItems = branches.Count() * programs.Count();

            foreach (var program in programs)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                var report = new StoredReport
                {
                    Title = program.Name,
                    AsOf  = asof
                };
                var reportData = new List <object[]>();

                report.HeaderRow = new string[]
                {
                    "Library System",
                    "Library",
                    "Signups",
                    "Achievers"
                };

                int programTotalUsers     = 0;
                int programTotalAchievers = 0;

                var systemIds = branches
                                .OrderBy(_ => _.SystemName)
                                .GroupBy(_ => _.SystemId)
                                .Select(_ => _.First().SystemId);
                foreach (var systemId in systemIds)
                {
                    foreach (var branch in branches.Where(_ => _.SystemId == systemId))
                    {
                        if (totalItems > 0)
                        {
                            UpdateProgress(progress,
                                           ++count * 100 / totalItems,
                                           $"{program.Name} - {branch.SystemName}",
                                           request.Name);
                        }

                        criterion.BranchId  = branch.Id;
                        criterion.ProgramId = program.Id;

                        int users = await _userRepository.GetCountAsync(criterion);

                        int achievers = await _userRepository.GetAchieverCountAsync(criterion);

                        reportData.Add(new object[]
                        {
                            branch.SystemName,
                            branch.Name,
                            users,
                            achievers
                        });

                        programTotalUsers     += users;
                        programTotalAchievers += achievers;

                        if (token.IsCancellationRequested)
                        {
                            break;
                        }
                    } // foreach branch

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                } // foreach system

                report.Data = reportData.ToArray();

                report.FooterRow = new object[]
                {
                    "Total",
                    string.Empty,
                    programTotalUsers,
                    programTotalAchievers
                };

                programTotals.Add(program.Id, (programTotalUsers, programTotalAchievers));

                double completion = 0;
                if (programTotalUsers > 0)
                {
                    completion = (double)programTotalAchievers * 100 / programTotalUsers;
                }

                var endDate = criterion.EndDate ?? asof;

                report.FooterText = new string[]
                {
                    $"Completion rate: {completion.ToString("N2")}%",
                    $"This report was run on {asof.ToString("g")} and contains data up to {endDate.ToString("g")}."
                };

                programReports.Add(report);
            } // foreach program

            var summaryReport = new StoredReport
            {
                Title = "Summary",
                AsOf  = asof
            };
            var summaryReportData = new List <object[]>();
            summaryReport.HeaderRow = new string[]
            {
                "Program",
                "Signups",
                "Achievers",
                "Achiever Points"
            }.ToArray();

            int signupTotal   = 0;
            int achieverTotal = 0;

            foreach (var program in programs)
            {
                var programData = programTotals[program.Id];
                summaryReportData.Add(new object[]
                {
                    program.Name,
                    programData.users,
                    programData.achievers,
                    program.AchieverPointAmount
                });

                signupTotal   += programData.users;
                achieverTotal += programData.achievers;
            }

            summaryReport.Data = summaryReportData.ToArray();

            summaryReport.FooterRow = new object[]
            {
                "Total",
                signupTotal,
                achieverTotal,
                string.Empty
            };

            double totalCompletion = 0;
            if (signupTotal > 0)
            {
                totalCompletion = (double)achieverTotal * 100 / signupTotal;
            }

            summaryReport.FooterText = new string[] {
                $"Completion rate: {totalCompletion.ToString("N2")}%"
            };
            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(summaryReport);
                foreach (var report in programReports)
                {
                    ReportSet.Reports.Add(report);
                }
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();

            var askIfFirstTime
                = await GetSiteSettingBoolAsync(criterion, SiteSettingKey.Users.AskIfFirstTime);

            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object>()
            {
                "System Name",
                "Branch Name",
                "Registered Users"
            };

            if (askIfFirstTime)
            {
                headerRow.Add("First time Participants");
            }

            headerRow.Add("Achievers");
            headerRow.Add("Challenges Completed");
            headerRow.Add("Badges Earned");

            var translations      = new Dictionary <string, ICollection <int?> >();
            var translationTotals = new Dictionary <string, long>();

            foreach (var program in await _programRepository.GetAllAsync((int)criterion.SiteId))
            {
                var pointTranslation = await _pointTranslationRepository
                                       .GetByProgramIdAsync(program.Id);

                string description = pointTranslation.ActivityDescriptionPlural;

                if (!translations.ContainsKey(description))
                {
                    translations.Add(description, new List <int?> {
                        pointTranslation.Id
                    });
                    translationTotals.Add(description, 0);
                    if (description.Length > 2)
                    {
                        headerRow.Add(description.First().ToString().ToUpper()
                                      + description.Substring(1));
                    }
                    else
                    {
                        headerRow.Add(description);
                    }
                }
                else
                {
                    translations[description].Add(pointTranslation.Id);
                }
            }

            headerRow.Add("Points Earned");
            report.HeaderRow = headerRow.ToArray();

            int count = 0;

            // running totals
            long totalRegistered = 0;
            long totalFirstTime  = 0;
            long totalAchiever   = 0;
            long totalChallenges = 0;
            long totalBadges     = 0;
            long totalPoints     = 0;

            var branches = criterion.SystemId != null
                ? await _branchRepository.GetBySystemAsync((int)criterion.SystemId)
                : await _branchRepository.GetAllAsync((int)criterion.SiteId);

            var systemIds = branches
                            .OrderBy(_ => _.SystemName)
                            .GroupBy(_ => _.SystemId)
                            .Select(_ => _.First().SystemId);

            foreach (var systemId in systemIds)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                foreach (var branch in branches.Where(_ => _.SystemId == systemId))
                {
                    UpdateProgress(progress,
                                   ++count * 100 / branches.Count(),
                                   $"Processing: {branch.SystemName} - {branch.Name}",
                                   request.Name);

                    criterion.SystemId = systemId;
                    criterion.BranchId = branch.Id;

                    int users = await _userRepository.GetCountAsync(criterion);

                    int achievers = await _userRepository.GetAchieverCountAsync(criterion);

                    long challenge = await _userLogRepository
                                     .CompletedChallengeCountAsync(criterion);

                    long badge = await _userLogRepository.EarnedBadgeCountAsync(criterion);

                    long points = await _userLogRepository.PointsEarnedTotalAsync(criterion);

                    totalRegistered += users;
                    totalAchiever   += achievers;
                    totalChallenges += challenge;
                    totalBadges     += badge;
                    totalPoints     += points;

                    var row = new List <object>()
                    {
                        branch.SystemName,
                        branch.Name,
                        users
                    };

                    if (askIfFirstTime)
                    {
                        int firstTime = await _userRepository.GetFirstTimeCountAsync(criterion);

                        totalFirstTime += firstTime;

                        row.Add(firstTime);
                    }

                    row.Add(achievers);
                    row.Add(challenge);
                    row.Add(badge);

                    foreach (var translationName in translations.Keys)
                    {
                        long total = await _userLogRepository.TranslationEarningsAsync(criterion,
                                                                                       translations[translationName]);

                        row.Add(total);
                        translationTotals[translationName] += total;
                    }

                    row.Add(points);
                    reportData.Add(row.ToArray());

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }

            report.Data = reportData.ToArray();

            // total row
            var footerRow = new List <object>()
            {
                "Total",
                string.Empty,
                totalRegistered
            };

            if (askIfFirstTime)
            {
                footerRow.Add(totalFirstTime);
            }

            footerRow.Add(totalAchiever);
            footerRow.Add(totalChallenges);
            footerRow.Add(totalBadges);

            foreach (var total in translationTotals.Values)
            {
                footerRow.Add(total);
            }

            footerRow.Add(totalPoints);

            report.FooterRow = footerRow.ToArray();
            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();
            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            report.HeaderRow = new object[] {
                "Rank",
                "System Name",
                "Branch Name",
                "Program",
                "Participant",
                "Points Earned"
            };

            int       count = 0;
            const int total = TopToShow;

            IEnumerable <User> users = await _userRepository.GetTopScoresAsync(criterion, total);

            foreach (var user in users.OrderByDescending(_ => _.PointsEarned))
            {
                UpdateProgress(progress,
                               ++count * 100 / users.Count(),
                               $"Processing: {count}/{users.Count()}",
                               request.Name);

                if (token.IsCancellationRequested)
                {
                    break;
                }

                var name = new StringBuilder(user.FirstName);
                if (!string.IsNullOrEmpty(user.LastName))
                {
                    name.Append(' ').Append(user.LastName);
                }
                if (!string.IsNullOrEmpty(user.Username))
                {
                    name.Append(" (").Append(user.Username).Append(')');
                }

                reportData.Add(new object[] {
                    count,
                    user.SystemName,
                    user.BranchName,
                    user.ProgramName,
                    name.ToString(),
                    user.PointsEarned
                });
            }

            report.Data = reportData.ToArray();
            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }
Beispiel #28
0
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <OperationStatus> progress = null)
        {
            #region Reporting initialization
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentNullException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();

            var askIfFirstTime
                = await GetSiteSettingBoolAsync(criterion, SiteSettingKey.Users.AskIfFirstTime);

            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object>()
            {
                "System Name",
                "Branch Name",
                "Registered Users"
            };

            if (askIfFirstTime)
            {
                headerRow.Add("First time Participants");
            }

            headerRow.Add("Achievers");

            report.HeaderRow = headerRow.ToArray();

            int count = 0;

            // running totals
            long totalRegistered = 0;
            long totalFirstTime  = 0;
            long totalAchiever   = 0;

            var branches = criterion.SystemId != null
                ? await _branchRepository.GetBySystemAsync((int)criterion.SystemId)
                : await _branchRepository.GetAllAsync((int)criterion.SiteId);

            var systemIds = branches
                            .OrderBy(_ => _.SystemName)
                            .GroupBy(_ => _.SystemId)
                            .Select(_ => _.First().SystemId);

            foreach (var systemId in systemIds)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                foreach (var branch in branches.Where(_ => _.SystemId == systemId))
                {
                    UpdateProgress(progress,
                                   ++count * 100 / branches.Count(),
                                   $"Processing: {branch.SystemName} - {branch.Name}",
                                   request.Name);

                    criterion.SystemId = systemId;
                    criterion.BranchId = branch.Id;

                    int users = await _userRepository.GetCountAsync(criterion);

                    int achievers = await _userRepository.GetAchieverCountAsync(criterion);

                    totalRegistered += users;
                    totalAchiever   += achievers;

                    var row = new List <object>()
                    {
                        branch.SystemName,
                        branch.Name,
                        users
                    };

                    if (askIfFirstTime)
                    {
                        int firstTime = await _userRepository.GetFirstTimeCountAsync(criterion);

                        totalFirstTime += firstTime;

                        row.Add(firstTime);
                    }

                    row.Add(achievers);

                    reportData.Add(row.ToArray());

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }

            report.Data = reportData.ToArray();

            // total row
            var footerRow = new List <object>()
            {
                "Total",
                string.Empty,
                totalRegistered
            };

            if (askIfFirstTime)
            {
                footerRow.Add(totalFirstTime);
            }

            footerRow.Add(totalAchiever);

            report.FooterRow = footerRow.ToArray();
            #endregion Collect data

            #region Finish up reporting
            _logger.LogInformation($"Report {GetType().Name} with criterion {criterion.Id} ran in {StopTimer()}");

            request.Success = !token.IsCancellationRequested;

            if (request.Success == true)
            {
                ReportSet.Reports.Add(report);
                request.Finished   = _serviceFacade.DateTimeProvider.Now;
                request.ResultJson = Newtonsoft.Json.JsonConvert.SerializeObject(ReportSet);
            }
            await _serviceFacade.ReportRequestRepository.UpdateSaveNoAuditAsync(request);

            #endregion Finish up reporting
        }
        public override async Task ExecuteAsync(ReportRequest request,
                                                CancellationToken token,
                                                IProgress <JobStatus> progress = null)
        {
            #region Reporting initialization
            request = await StartRequestAsync(request);

            var criterion
                = await _serviceFacade.ReportCriterionRepository.GetByIdAsync(request.ReportCriteriaId)
                  ?? throw new GraException($"Report criteria {request.ReportCriteriaId} for report request id {request.Id} could not be found.");

            if (criterion.SiteId == null)
            {
                throw new ArgumentException(nameof(criterion.SiteId));
            }

            var report = new StoredReport
            {
                Title = ReportAttribute?.Name,
                AsOf  = _serviceFacade.DateTimeProvider.Now
            };
            var reportData = new List <object[]>();

            var askIfFirstTime
                = await GetSiteSettingBoolAsync(criterion, SiteSettingKey.Users.AskIfFirstTime);

            #endregion Reporting initialization

            #region Collect data
            UpdateProgress(progress, 1, "Starting report...", request.Name);

            // header row
            var headerRow = new List <object> {
                "School Name",
                "Registered Users"
            };

            if (askIfFirstTime)
            {
                headerRow.Add("First time Participants");
            }

            headerRow.Add("Achievers");

            report.HeaderRow = headerRow.ToArray();

            int count = 0;

            // running totals
            long totalRegistered = 0;
            long totalFirstTime  = 0;
            long totalAchiever   = 0;

            ICollection <School> schools = null;

            if (criterion.SchoolId != null)
            {
                schools = new List <School>()
                {
                    await _schoolRepository.GetByIdAsync((int)criterion.SchoolId)
                };
            }
            else if (criterion.SchoolDistrictId != null)
            {
                schools = await _schoolRepository.GetAllAsync((int)criterion.SiteId,
                                                              criterion.SchoolDistrictId);
            }

            if (schools == null)
            {
                throw new GraFatalException("Could not find any school(s) to report on.");
            }

            foreach (var school in schools)
            {
                if (token.IsCancellationRequested)
                {
                    break;
                }

                UpdateProgress(progress,
                               ++count * 100 / schools.Count,
                               $"Processing: {school.Name}",
                               request.Name);

                criterion.SchoolDistrictId = null;
                criterion.SchoolId         = school.Id;

                int users = await _userRepository.GetCountAsync(criterion);

                int achievers = await _userRepository.GetAchieverCountAsync(criterion);

                totalRegistered += users;
                totalAchiever   += achievers;

                var row = new List <object>
                {
                    school.Name,
                    users
                };

                if (askIfFirstTime)
                {
                    int firstTime = await _userRepository.GetFirstTimeCountAsync(criterion);

                    totalFirstTime += firstTime;

                    row.Add(firstTime);
                }

                row.Add(achievers);

                reportData.Add(row.ToArray());
            }

            report.Data = reportData.ToArray();

            // total row
            var footerRow = new List <object>
            {
                "Total",
                totalRegistered
            };

            if (askIfFirstTime)
            {
                footerRow.Add(totalFirstTime);
            }

            footerRow.Add(totalAchiever);

            report.FooterRow = footerRow.ToArray();
            #endregion Collect data

            #region Finish up reporting
            if (!token.IsCancellationRequested)
            {
                ReportSet.Reports.Add(report);
            }
            await FinishRequestAsync(request, !token.IsCancellationRequested);

            #endregion Finish up reporting
        }