Phase 1: Introduce typed repository interfaces and report service stubs

Six IUnitOfWork properties upgraded from generic IRepository<T> to domain-specific
typed interfaces (IJobRepository, IQuoteRepository, IInvoiceRepository,
ICustomerRepository, IBillRepository, IPurchaseOrderRepository). Each backed by a
concrete typed repository that encapsulates complex include chains previously
inlined in controllers.

Also adds IFinancialReportService and IOperationalReportService stub implementations
(NotImplementedException placeholders) to Application.Interfaces and Infrastructure.Services,
registered in Program.cs. These are the migration targets for ReportsController's
aggregate query methods in Phase 2.

No controller behaviour changed in this commit — all callers still compile because
typed interfaces extend IRepository<T>.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-27 19:54:10 -04:00
parent 92dc3ebd08
commit 80b0e547cc
22 changed files with 746 additions and 30 deletions
@@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore;
using PowderCoating.Application.DTOs.Accounting;
using PowderCoating.Application.Interfaces;
using PowderCoating.Infrastructure.Data;
namespace PowderCoating.Infrastructure.Services;
/// <summary>
/// Implements financial aggregate reports using direct DbContext access with AsNoTracking.
/// Query logic is migrated here from <c>ReportsController</c> as each report action is
/// converted during Phase 2/3 of the data-access architecture migration.
/// See <c>docs/DATA_ACCESS_ARCHITECTURE.md</c> for the full migration plan.
/// </summary>
public class FinancialReportService : IFinancialReportService
{
private readonly ApplicationDbContext _context;
public FinancialReportService(ApplicationDbContext context)
{
_context = context;
}
/// <inheritdoc/>
/// <remarks>Implemented — migrated from <c>ReportsController.ProfitAndLoss</c> in Phase 2.</remarks>
public Task<ProfitAndLossDto> GetProfitAndLossAsync(int companyId, DateTime from, DateTime to)
=> throw new NotImplementedException("Migrate from ReportsController.ProfitAndLoss — Phase 2.");
/// <inheritdoc/>
public Task<BalanceSheetDto> GetBalanceSheetAsync(int companyId, DateTime asOf)
=> throw new NotImplementedException("Migrate from ReportsController.BalanceSheet — Phase 2.");
/// <inheritdoc/>
public Task<ArAgingReportDto> GetArAgingAsync(int companyId, DateTime asOf)
=> throw new NotImplementedException("Migrate from ReportsController.ArAging — Phase 2.");
/// <inheritdoc/>
public Task<SalesIncomeReportDto> GetSalesAndIncomeAsync(int companyId, DateTime from, DateTime to)
=> throw new NotImplementedException("Migrate from ReportsController.SalesAndIncome — Phase 2.");
}
@@ -0,0 +1,28 @@
using PowderCoating.Application.Interfaces;
using PowderCoating.Infrastructure.Data;
namespace PowderCoating.Infrastructure.Services;
/// <summary>
/// Implements operational aggregate reports using direct DbContext access with AsNoTracking.
/// Query logic is migrated here from <c>ReportsController</c> as each report action is
/// converted during Phase 2/3 of the data-access architecture migration.
/// See <c>docs/DATA_ACCESS_ARCHITECTURE.md</c> for the full migration plan.
/// </summary>
public class OperationalReportService : IOperationalReportService
{
private readonly ApplicationDbContext _context;
public OperationalReportService(ApplicationDbContext context)
{
_context = context;
}
/// <inheritdoc/>
public Task<JobCycleTimeReport> GetJobCycleTimeAsync(int companyId, int months)
=> throw new NotImplementedException("Migrate from ReportsController.JobCycleTime — Phase 2.");
/// <inheritdoc/>
public Task<PowderUsageReport> GetPowderUsageAsync(int companyId, int months)
=> throw new NotImplementedException("Migrate from ReportsController.PowderUsage — Phase 2.");
}