From 86a293a92750ff06db8ba0f83f94ce8978957255 Mon Sep 17 00:00:00 2001 From: Scott Pouliot Date: Wed, 10 Jun 2026 21:34:57 -0400 Subject: [PATCH] Add one-click Demo Company reset for tutorial recording prep New ResetDemoCompany POST action wipes all seeded data (customers, jobs, quotes, invoices, inventory, equipment, catalog, pricing tiers, operating costs) from the DEMO company and immediately re-seeds with fresh records dated relative to today. Seed data already used relative dates so every reset produces a realistic, current-looking dataset. View adds a red "Reset Demo Company" card at the top of the Seed Data page, visible only when the DEMO company exists. Single button with confirm dialog; shows exactly what will be wiped and what will be preserved (user accounts, company settings, lookup tables). Co-Authored-By: Claude Sonnet 4.6 --- .../Controllers/SeedDataController.cs | 69 +++++++++++++++++++ .../Views/SeedData/Index.cshtml | 38 ++++++++++ 2 files changed, 107 insertions(+) diff --git a/src/PowderCoating.Web/Controllers/SeedDataController.cs b/src/PowderCoating.Web/Controllers/SeedDataController.cs index 24dcd42..351f900 100644 --- a/src/PowderCoating.Web/Controllers/SeedDataController.cs +++ b/src/PowderCoating.Web/Controllers/SeedDataController.cs @@ -106,6 +106,75 @@ public class SeedDataController : Controller return RedirectToAction(nameof(Index)); } + /// + /// Wipes all seeded data from the DEMO company and immediately re-seeds it with fresh demo data + /// so all dates are current. Intended for tutorial recording resets — one click returns the demo + /// company to a clean, realistic state without touching any other tenant. + /// + [HttpPost] + [ValidateAntiForgeryToken] + public async Task ResetDemoCompany() + { + try + { + var companies = await _seedDataService.GetCompaniesAsync(); + var demo = companies.FirstOrDefault(c => c.CompanyCode == "DEMO"); + if (demo == null) + { + TempData["ErrorMessage"] = "Demo company (code: DEMO) not found. Run Seed System Data first."; + return RedirectToAction(nameof(Index)); + } + + // Remove all seed data categories + var removeOptions = new RemoveSeedDataOptions + { + Customers = true, + InventoryItems = true, + Equipment = true, + Catalog = true, + PricingTiers = true, + OperatingCosts = true, + }; + + var removeResult = await _seedDataService.RemoveSeedDataAsync(demo.Id, removeOptions); + if (!removeResult.Success) + { + TempData["ErrorMessage"] = $"Wipe step failed: {removeResult.Message}"; + return RedirectToAction(nameof(Index)); + } + + // Re-seed with today's dates + var seedResult = await _seedDataService.SeedCompanyDataAsync(demo.Id); + + if (seedResult.Success) + { + TempData["SuccessMessage"] = $"Demo company reset complete. {seedResult.ItemsSeeded} records re-seeded with today's dates."; + TempData["SeedDetails"] = string.Join("|", seedResult.Details); + TempData["ItemsSeeded"] = seedResult.ItemsSeeded; + + if (seedResult.Warnings.Any()) + { + TempData["WarningMessage"] = $"{seedResult.ItemsSkipped} item(s) were skipped"; + var displayWarnings = seedResult.Warnings.Take(30).ToList(); + if (seedResult.Warnings.Count > 30) + displayWarnings.Add($"… and {seedResult.Warnings.Count - 30} more (see logs)"); + TempData["SeedWarnings"] = string.Join("|", displayWarnings); + } + } + else + { + TempData["ErrorMessage"] = $"Wipe succeeded but re-seed failed: {seedResult.Message}"; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error resetting demo company"); + TempData["ErrorMessage"] = $"An error occurred during demo reset: {ex.Message}"; + } + + return RedirectToAction(nameof(Index)); + } + /// /// Removes previously seeded demo data from a company according to the supplied options (e.g., jobs only, or all data). Used during QA/demo resets to return a company to a clean state without a full database drop. /// diff --git a/src/PowderCoating.Web/Views/SeedData/Index.cshtml b/src/PowderCoating.Web/Views/SeedData/Index.cshtml index a5dadae..d208e7b 100644 --- a/src/PowderCoating.Web/Views/SeedData/Index.cshtml +++ b/src/PowderCoating.Web/Views/SeedData/Index.cshtml @@ -98,6 +98,44 @@ } + + @{ + var demoCompany = Model?.FirstOrDefault(c => c.CompanyCode == "DEMO"); + } + @if (demoCompany != null) + { +
+
+ +
Reset Demo Company
+ Tutorial Prep +
+
+

+ Wipes all seeded data from the Demo Company and immediately re-seeds it with + fresh records dated relative to today. Use this before every recording session + so jobs, quotes, invoices, and AR aging always look current. +

+
    +
  • Removes: customers, jobs, quotes, invoices, inventory, equipment, catalog, pricing tiers, operating costs
  • +
  • Re-seeds: 100 customers, 50 jobs across all statuses, quotes, invoices, inventory transactions, vendor bills, appointments — all dated from today
  • +
  • Preserves: user accounts, company settings, lookup tables (job statuses, priorities, etc.)
  • +
+
+ + This permanently deletes and recreates all demo data. Any manual edits made to the demo company will be lost. +
+
+ @Html.AntiForgeryToken() + +
+
+
+ } +