public static Job CreateJob(ArchiveAuditArgs args) => new Job { JobType = JobType.ArchiveAudit, ArchiveAuditArgs = args };
private async Task ArchiveAudit(ArchiveAuditArgs args) { try { var db = _blogContext; var udb = _usersContext; var blogDecisions = db.BlogAudits.Where(ba => ba.BlogID == args.BlogId && (ba.AuditAction == BlogAudit.Action.Approve || ba.AuditAction == BlogAudit.Action.Deny)); List <BlogAudit> latestAudits; int version = 1; if (args.IsAmend) { var latestDecision = blogDecisions.OrderByDescending(ba => ba.BlogVersion).FirstOrDefault(); if (latestDecision != null) { db.BlogAudits.Remove(latestDecision); db.SaveChanges(); latestAudits = db.BlogAudits.Where(bb => bb.BlogID == args.BlogId && bb.BlogVersion == latestDecision.BlogVersion).ToList(); } else { latestAudits = db.BlogAudits.Where(bb => bb.BlogID == args.BlogId && bb.BlogVersion == 1).ToList(); } } else { version = blogDecisions.DefaultIfEmpty().Max(bm => bm == null ? 0 : bm.BlogVersion) + 1; latestAudits = db.BlogAudits.Where(bb => bb.BlogID == args.BlogId && bb.BlogVersion >= version).ToList(); } if (latestAudits.Count > 0) { version = latestAudits[0].BlogVersion; } // It is possible the auditor also voted. In that case update the vote as decision, don't calculate the auditor's statistics. var blogAudit = latestAudits.SingleOrDefault(la => la.BlogID == args.BlogId && la.Auditor == args.Auditor && la.BlogVersion == version) ?? db.BlogAudits.Add(new BlogAudit { Auditor = args.Auditor, BlogID = args.BlogId, BlogVersion = version }); blogAudit.AuditAction = args.Action; blogAudit.AuditDate = DateTime.Now; blogAudit.Reason = args.Reason; var currentStat = latestAudits.Where(ba => ba.AuditAction == BlogAudit.Action.VoteApprove || ba.AuditAction == BlogAudit.Action.VoteDeny) .ToDictionary(la => la.Auditor.ToLower(), la => (la.AuditAction == BlogAudit.Action.VoteApprove && args.Action == BlogAudit.Action.Approve) || (la.AuditAction == BlogAudit.Action.VoteDeny && args.Action == BlogAudit.Action.Deny)); var latestAuditors = currentStat.Keys; if (latestAuditors.Count > 0) { var stats = db.BlogAudits.Where(ba => ba.AuditAction == BlogAudit.Action.Approve || ba.AuditAction == BlogAudit.Action.Deny) .GroupJoin(db.BlogAudits.Where(ba => latestAuditors.Contains(ba.Auditor) && (ba.AuditAction == BlogAudit.Action.VoteApprove || ba.AuditAction == BlogAudit.Action.VoteDeny)), ba => new { ba.BlogID, ba.BlogVersion }, la => new { la.BlogID, la.BlogVersion }, (ba, la) => new { Decision = ba, Votes = la }) .SelectMany(d => d.Votes, (d, v) => new { Auditor = v.Auditor, Correct = (v.AuditAction == BlogAudit.Action.VoteApprove && d.Decision.AuditAction == BlogAudit.Action.Approve) || (v.AuditAction == BlogAudit.Action.VoteDeny && d.Decision.AuditAction == BlogAudit.Action.Deny) }).GroupBy(v => v.Auditor).ToDictionary(g => g.Key.ToLower(), g => new { CorrectCount = g.Count(d => d.Correct), Total = g.Count() }); var usersToUpdate = stats.Keys.Concat(currentStat.Keys); var updates = udb.Auditors.Where(a => usersToUpdate.Contains(a.User.UserName)).Select(a => new { a.User.UserName, Auditor = a }); foreach (var update in updates) { int total = 0, correctcount = 0; if (stats.ContainsKey(update.UserName.ToLower())) { var stat = stats[update.UserName.ToLower()]; total = stat.Total; correctcount = stat.CorrectCount; } update.Auditor.AuditCount = total + 1; update.Auditor.CorrectCount = correctcount + (currentStat[update.UserName.ToLower()] ? 1 : 0); } } await Task.WhenAll(udb.SaveChangesAsync(), db.SaveChangesAsync()); } catch (Exception e) { _logger.LogError(e, "Error running ArchiveAudit"); } }