Ejemplo n.º 1
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
        }