using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using PowderCoating.Core.Interfaces; using PowderCoating.Shared.Constants; namespace PowderCoating.Web.Controllers; /// /// SuperAdmin view of per-company SMS terms agreement history. /// Shows which companies have accepted the current SMS terms, who accepted them, /// and the full acceptance log for each company. /// [Authorize(Policy = AppConstants.Policies.SuperAdminOnly)] public class SmsAgreementsController : Controller { private readonly IUnitOfWork _unitOfWork; private readonly ILogger _logger; public SmsAgreementsController(IUnitOfWork unitOfWork, ILogger logger) { _unitOfWork = unitOfWork; _logger = logger; } /// /// Lists every company with its current SMS agreement status and full acceptance history. /// Uses IgnoreQueryFilters on both queries so deleted/inactive companies and all historical /// agreement records are included in the audit view. /// public async Task Index(string? search = null, string? filter = null) { var companies = await _unitOfWork.Companies.GetAllAsync(ignoreQueryFilters: true); var allAgreements = await _unitOfWork.CompanySmsAgreements.GetAllAsync(ignoreQueryFilters: true); var agreementsByCompany = allAgreements .GroupBy(a => a.CompanyId) .ToDictionary(g => g.Key, g => g.OrderByDescending(a => a.AgreedAt).ToList()); var rows = companies .OrderBy(c => c.CompanyName) .Select(c => { var agreements = agreementsByCompany.TryGetValue(c.Id, out var list) ? list : []; var current = agreements.FirstOrDefault(a => a.TermsVersion == AppConstants.SmsTermsVersion); return new CompanySmsRow { CompanyId = c.Id, CompanyName = c.CompanyName ?? "(unnamed)", SmsEnabled = c.SmsEnabled, SmsDisabledByAdmin = c.SmsDisabledByAdmin, CurrentAgreement = current, LatestAgreement = agreements.FirstOrDefault(), AllAgreements = agreements, IsDeleted = c.IsDeleted }; }) .ToList(); // Filter rows = filter switch { "accepted" => rows.Where(r => r.CurrentAgreement != null).ToList(), "pending" => rows.Where(r => r.CurrentAgreement == null).ToList(), "enabled" => rows.Where(r => r.SmsEnabled).ToList(), "disabled" => rows.Where(r => r.SmsDisabledByAdmin).ToList(), _ => rows }; if (!string.IsNullOrWhiteSpace(search)) rows = rows.Where(r => r.CompanyName.Contains(search, StringComparison.OrdinalIgnoreCase)).ToList(); ViewBag.Search = search; ViewBag.Filter = filter ?? "all"; ViewBag.CurrentTermsVersion = AppConstants.SmsTermsVersion; // Stats (pre-filter totals) var all = companies.ToList(); ViewBag.TotalCompanies = all.Count(c => !c.IsDeleted); ViewBag.AcceptedCount = agreementsByCompany.Count(kvp => kvp.Value.Any(a => a.TermsVersion == AppConstants.SmsTermsVersion) && !all.FirstOrDefault(c => c.Id == kvp.Key)?.IsDeleted == true); ViewBag.SmsEnabledCount = all.Count(c => !c.IsDeleted && c.SmsEnabled); return View(rows); } } /// View model for one company row on the SMS agreements page. public class CompanySmsRow { public int CompanyId { get; set; } public string CompanyName { get; set; } = string.Empty; public bool SmsEnabled { get; set; } public bool SmsDisabledByAdmin { get; set; } public bool IsDeleted { get; set; } public PowderCoating.Core.Entities.CompanySmsAgreement? CurrentAgreement { get; set; } public PowderCoating.Core.Entities.CompanySmsAgreement? LatestAgreement { get; set; } public List AllAgreements { get; set; } = []; }