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
@@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using PowderCoating.Core.Entities;
using PowderCoating.Core.Interfaces;
using PowderCoating.Core.Interfaces.Repositories;
using PowderCoating.Infrastructure.Data;
namespace PowderCoating.Infrastructure.Repositories;
@@ -43,13 +44,13 @@ public class UnitOfWork : IUnitOfWork
private IRepository<PowderUsageLog>? _powderUsageLogs;
// Core repositories
private IRepository<Customer>? _customers;
private IRepository<Job>? _jobs;
private ICustomerRepository? _customers;
private IJobRepository? _jobs;
private IRepository<JobDailyPriority>? _jobDailyPriorities;
private IRepository<JobItem>? _jobItems;
private IRepository<JobItemCoat>? _jobItemCoats;
private IRepository<JobChangeHistory>? _jobChangeHistories;
private IRepository<Quote>? _quotes;
private IQuoteRepository? _quotes;
private IRepository<QuotePhoto>? _quotePhotos;
private IRepository<QuoteItem>? _quoteItems;
private IRepository<QuoteItemCoat>? _quoteItemCoats;
@@ -109,7 +110,7 @@ public class UnitOfWork : IUnitOfWork
private IRepository<GiftCertificateRedemption>? _giftCertificateRedemptions;
// Purchase Orders
private IRepository<PurchaseOrder>? _purchaseOrders;
private IPurchaseOrderRepository? _purchaseOrders;
private IRepository<PurchaseOrderItem>? _purchaseOrderItems;
// Oven Scheduling
@@ -117,14 +118,14 @@ public class UnitOfWork : IUnitOfWork
private IRepository<OvenBatchItem>? _ovenBatchItems;
// Invoices, Payments & Deposits
private IRepository<Invoice>? _invoices;
private IInvoiceRepository? _invoices;
private IRepository<InvoiceItem>? _invoiceItems;
private IRepository<Payment>? _payments;
private IRepository<Deposit>? _deposits;
// Expense Tracking / Accounts Payable
private IRepository<Account>? _accounts;
private IRepository<Bill>? _bills;
private IBillRepository? _bills;
private IRepository<BillLineItem>? _billLineItems;
private IRepository<BillPayment>? _billPayments;
private IRepository<Expense>? _expenses;
@@ -171,12 +172,12 @@ public class UnitOfWork : IUnitOfWork
// Core repositories
/// <summary>Repository for <see cref="Customer"/> records (commercial and non-commercial); tenant-filtered with soft delete.</summary>
public IRepository<Customer> Customers =>
_customers ??= new Repository<Customer>(_context);
public ICustomerRepository Customers =>
_customers ??= new CustomerRepository(_context);
/// <summary>Repository for <see cref="Job"/> records progressing through the 16-status lifecycle; tenant-filtered with soft delete.</summary>
public IRepository<Job> Jobs =>
_jobs ??= new Repository<Job>(_context);
public IJobRepository Jobs =>
_jobs ??= new JobRepository(_context);
/// <summary>Repository for <see cref="JobDailyPriority"/> overrides that let supervisors re-order the shop floor queue.</summary>
public IRepository<JobDailyPriority> JobDailyPriorities =>
@@ -195,8 +196,8 @@ public class UnitOfWork : IUnitOfWork
_jobChangeHistories ??= new Repository<JobChangeHistory>(_context);
/// <summary>Repository for <see cref="Quote"/> records with multi-item pricing; tenant-filtered with soft delete.</summary>
public IRepository<Quote> Quotes =>
_quotes ??= new Repository<Quote>(_context);
public IQuoteRepository Quotes =>
_quotes ??= new QuoteRepository(_context);
/// <summary>Repository for <see cref="QuotePhoto"/> AI photo uploads; tenant-filtered with soft delete.</summary>
public IRepository<QuotePhoto> QuotePhotos =>
@@ -405,8 +406,8 @@ public class UnitOfWork : IUnitOfWork
// Purchase Orders
/// <summary>Repository for <see cref="PurchaseOrder"/> vendor purchase orders; tenant-filtered with soft delete.</summary>
public IRepository<PurchaseOrder> PurchaseOrders =>
_purchaseOrders ??= new Repository<PurchaseOrder>(_context);
public IPurchaseOrderRepository PurchaseOrders =>
_purchaseOrders ??= new PurchaseOrderRepository(_context);
/// <summary>Repository for <see cref="PurchaseOrderItem"/> line-items on a purchase order; cascade-deleted with the PO.</summary>
public IRepository<PurchaseOrderItem> PurchaseOrderItems =>
@@ -423,8 +424,8 @@ public class UnitOfWork : IUnitOfWork
// Invoices, Payments & Deposits
/// <summary>Repository for <see cref="Invoice"/> customer invoices (1:1 with Job); tenant-filtered with soft delete.</summary>
public IRepository<Invoice> Invoices =>
_invoices ??= new Repository<Invoice>(_context);
public IInvoiceRepository Invoices =>
_invoices ??= new InvoiceRepository(_context);
/// <summary>Repository for <see cref="InvoiceItem"/> line-items on an invoice; tenant-filtered with soft delete.</summary>
public IRepository<InvoiceItem> InvoiceItems =>
@@ -447,8 +448,8 @@ public class UnitOfWork : IUnitOfWork
_accounts ??= new Repository<Account>(_context);
/// <summary>Repository for <see cref="Bill"/> vendor bills (accounts payable); tenant-filtered with soft delete.</summary>
public IRepository<Bill> Bills =>
_bills ??= new Repository<Bill>(_context);
public IBillRepository Bills =>
_bills ??= new BillRepository(_context);
/// <summary>Repository for <see cref="BillLineItem"/> expense line-items on a vendor bill; each assigned to a chart-of-accounts entry.</summary>
public IRepository<BillLineItem> BillLineItems =>