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 }
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 }
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 }