using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using ProposalSystem.Application.DTOs; using ProposalSystem.Domain.Entities; using ProposalSystem.Infrastructure.Data; namespace ProposalSystem.Api.Controllers; [ApiController] [Route("api/admin")] [Authorize(Roles = "admins,sysadmins")] public class AdminController : ControllerBase { private readonly ProposalDbContext _db; public AdminController(ProposalDbContext db) { _db = db; } [HttpGet("dashboard")] public async Task> GetDashboard(CancellationToken ct) { // Fix: API-M7 — AsNoTracking on read-only dashboard queries var pendingCount = await _db.Proposals .AsNoTracking() .CountAsync(p => p.Status == ProposalStatus.InReview, ct); var weekStart = DateTime.UtcNow.AddDays(-7); var approvedThisWeek = await _db.Proposals .AsNoTracking() .CountAsync(p => p.ApprovedAt >= weekStart, ct); var approvedCount = await _db.Proposals .AsNoTracking() .CountAsync(p => p.ApprovedAt.HasValue, ct); double avgTurnaround = 0; if (approvedCount > 0) { var recentApproved = await _db.Proposals .AsNoTracking() .Where(p => p.ApprovedAt.HasValue) .OrderByDescending(p => p.ApprovedAt) .Take(200) .Select(p => new { p.ApprovedAt, p.SubmittedAt }) .ToListAsync(ct); avgTurnaround = recentApproved.Average(p => (p.ApprovedAt!.Value - p.SubmittedAt).TotalHours); } var totalProposals = await _db.Proposals.AsNoTracking().CountAsync(ct); return Ok(new DashboardResponse(pendingCount, approvedThisWeek, avgTurnaround, totalProposals)); } }