Phases 3 & 4: Complete data access architecture migration
Phase 3 — eliminated ApplicationDbContext from all non-exempt controllers, routing all data access through IUnitOfWork. Added IPlainRepository<T> for the four platform entities (Announcement, BannedIp, DashboardTip, ReleaseNote) that intentionally don't extend BaseEntity and therefore can't use the constrained IRepository<T>. Added permanent-exception comments to the 18 controllers that legitimately retain direct DbContext access (Identity infra, cross-tenant platform ops, bulk streaming exports). Phase 4 — added EnforceDataAccessArchitecture() to Program.cs, a startup gate that reflects over every Controller subclass and throws at boot if any non-exempt controller injects ApplicationDbContext. The app cannot start with a violation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
namespace PowderCoating.Application.Interfaces;
|
||||
|
||||
/// <summary>Pre-aggregated AI call counts for one company across four time windows.</summary>
|
||||
public record AiCompanyUsage(int CompanyId, int Today, int Last7Days, int Last30Days, int AllTime);
|
||||
|
||||
/// <summary>Count of AI calls for a specific feature within a company (last 30 days).</summary>
|
||||
public record AiFeatureStat(int CompanyId, string Feature, int Count);
|
||||
|
||||
/// <summary>Bundled result returned by <see cref="IAiUsageReportService.GetReportDataAsync"/>.</summary>
|
||||
public record AiUsageReportData(
|
||||
List<AiCompanyUsage> UsageByCompany,
|
||||
List<AiFeatureStat> FeatureStats,
|
||||
Dictionary<int, int> PhotoCountsByCompany);
|
||||
|
||||
/// <summary>
|
||||
/// Read-only service for the platform AI usage analytics report. Queries <c>AiUsageLogs</c>
|
||||
/// and <c>QuotePhotos</c> (cross-tenant, non-BaseEntity) via <c>ApplicationDbContext</c>
|
||||
/// directly so that <see cref="AiUsageReportController"/> does not need a direct DB context reference.
|
||||
/// Implemented in Infrastructure; used as Tier-3 aggregate report service.
|
||||
/// </summary>
|
||||
public interface IAiUsageReportService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all the aggregated AI usage data needed to render the platform AI usage report:
|
||||
/// per-company call counts across today / 7-day / 30-day / all-time windows,
|
||||
/// feature stats for the last 30 days, and AI photo upload counts per company.
|
||||
/// </summary>
|
||||
Task<AiUsageReportData> GetReportDataAsync();
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using PowderCoating.Core.Entities;
|
||||
|
||||
namespace PowderCoating.Application.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
@@ -22,4 +24,25 @@ public interface IOperationalReportService
|
||||
|
||||
/// <summary>Returns powder usage (lbs and cost) broken down by color and vendor.</summary>
|
||||
Task<PowderUsageReport> GetPowderUsageAsync(int companyId, int months);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all active (non-deleted, non-voided) bills with their Vendor and non-deleted
|
||||
/// Payments navigations loaded. Used by Analytics, ExpensesAp, and AI accounting actions
|
||||
/// so those controllers do not need a direct ApplicationDbContext reference.
|
||||
/// </summary>
|
||||
Task<List<Bill>> GetActiveBillsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns all non-deleted direct expenses with their ExpenseAccount navigation loaded.
|
||||
/// Used by Analytics, ExpensesAp, and AI accounting actions so those controllers do not
|
||||
/// need a direct ApplicationDbContext reference.
|
||||
/// </summary>
|
||||
Task<List<Expense>> GetAllExpensesAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full job status history log with FromStatus and ToStatus navigations
|
||||
/// loaded. Used by Analytics and JobCycleTime so those actions do not need a direct
|
||||
/// ApplicationDbContext reference.
|
||||
/// </summary>
|
||||
Task<List<JobStatusHistory>> GetAllJobStatusHistoryAsync();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user