using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using PowderCoating.Core.Entities; using PowderCoating.Core.Interfaces; using PowderCoating.Shared.Constants; using PowderCoating.Web.ViewModels.Platform; namespace PowderCoating.Web.Controllers; [Authorize(Policy = AppConstants.Policies.SuperAdminOnly)] public class OnboardingProgressController : Controller { private readonly IUnitOfWork _unitOfWork; private readonly UserManager _userManager; public OnboardingProgressController(IUnitOfWork unitOfWork, UserManager userManager) { _unitOfWork = unitOfWork; _userManager = userManager; } /// /// Shows onboarding and activation status for every tenant company. SuperAdmin-only. /// Reads CompanyPreferences fields written by the setup wizard, guided activation, /// and the jobs/quotes/invoices controllers to give a cross-tenant activation funnel view. /// public async Task Index() { var companies = (await _unitOfWork.Companies.GetAllAsync( ignoreQueryFilters: true, c => c.Preferences!)) .Where(c => !c.IsDeleted) .OrderBy(c => c.CompanyName) .ToList(); var rows = companies.Select(c => BuildRow(c)).ToList(); return View(new OnboardingProgressIndexViewModel { Rows = rows }); } private static OnboardingProgressRowViewModel BuildRow(Company company) { var prefs = company.Preferences; var wizardDone = prefs?.SetupWizardCompleted ?? false; // Mirror the same 6-step logic used in DashboardController.BuildShopProgressWidgetAsync // Steps: first job/quote, status history (unknown here — omit), first invoice, // team size (unknown here — omit), customized lookups (unknown — omit), payment defaults. // We track the 3 date-stamped milestones we can derive from prefs alone. int steps = 0; if (prefs?.FirstJobCreatedAt.HasValue == true || prefs?.FirstQuoteCreatedAt.HasValue == true) steps++; if (prefs?.FirstInvoiceCreatedAt.HasValue == true) steps++; if (prefs?.FirstWorkflowCompletedAt.HasValue == true) steps++; const int total = 3; OnboardingStatus status; if (!wizardDone) status = OnboardingStatus.NotStarted; else if (prefs?.FirstWorkflowCompletedAt.HasValue == true && prefs.GuidedActivationDismissedAt.HasValue) status = OnboardingStatus.Dismissed; else if (prefs?.FirstWorkflowCompletedAt.HasValue == true) status = OnboardingStatus.Complete; else if (steps > 0) status = OnboardingStatus.InProgress; else status = OnboardingStatus.NotStarted; return new OnboardingProgressRowViewModel { CompanyId = company.Id, CompanyName = company.CompanyName ?? "Unknown", WizardCompleted = wizardDone, OnboardingPath = prefs?.OnboardingPath, StepsCompleted = steps, TotalSteps = total, FirstJobCreatedAt = prefs?.FirstJobCreatedAt, FirstQuoteCreatedAt = prefs?.FirstQuoteCreatedAt, FirstInvoiceCreatedAt = prefs?.FirstInvoiceCreatedAt, FirstWorkflowCompletedAt = prefs?.FirstWorkflowCompletedAt, GuidedActivationDismissedAt = prefs?.GuidedActivationDismissedAt, Status = status }; } }