90bc0d965f
Migrated InvoicesController, QuotesController, JobsController, BillsController, PurchaseOrdersController, and CustomersController to route all data access through IUnitOfWork typed/generic repositories instead of injecting ApplicationDbContext directly. New typed repositories added: IJobRepository (GetScheduledJobsForDateAsync, GetActiveJobsForMobileAsync, LoadForCostingAsync), INotificationLogRepository (GetLatestForJobAsync, GetAllForJobAsync), IQuoteRepository (GetItemsWithCoatsAsync with CatalogItem eager load + AsNoTracking), and IJobRepository.GetOrphanedConversionJobAsync. All EF complex include chains relocated into repository methods; controllers now call named query methods rather than composing raw IQueryable chains. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
93 lines
3.5 KiB
C#
93 lines
3.5 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using PowderCoating.Core.Entities;
|
|
using PowderCoating.Core.Enums;
|
|
using PowderCoating.Core.Interfaces.Repositories;
|
|
using PowderCoating.Infrastructure.Data;
|
|
|
|
namespace PowderCoating.Infrastructure.Repositories;
|
|
|
|
/// <summary>
|
|
/// Typed repository for <see cref="Bill"/> that provides domain-specific multi-level
|
|
/// include queries previously expressed inline in <c>BillsController</c>.
|
|
/// </summary>
|
|
public class BillRepository : Repository<Bill>, IBillRepository
|
|
{
|
|
public BillRepository(ApplicationDbContext context) : base(context) { }
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<Bill?> LoadForViewAsync(int id)
|
|
{
|
|
return await _context.Bills
|
|
.Where(b => b.Id == id && !b.IsDeleted)
|
|
.Include(b => b.Vendor)
|
|
.Include(b => b.APAccount)
|
|
.Include(b => b.LineItems.Where(li => !li.IsDeleted))
|
|
.ThenInclude(li => li.Account)
|
|
.Include(b => b.LineItems.Where(li => !li.IsDeleted))
|
|
.ThenInclude(li => li.Job)
|
|
.Include(b => b.Payments.Where(p => !p.IsDeleted))
|
|
.ThenInclude(p => p.BankAccount)
|
|
.FirstOrDefaultAsync();
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<Bill?> LoadForEditAsync(int id)
|
|
{
|
|
return await _context.Bills
|
|
.Where(b => b.Id == id && !b.IsDeleted)
|
|
.Include(b => b.LineItems.Where(li => !li.IsDeleted))
|
|
.FirstOrDefaultAsync();
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<List<Bill>> GetForIndexAsync(string? statusFilter, string? searchTerm, decimal? searchAmount)
|
|
{
|
|
var query = _context.Bills
|
|
.Include(b => b.Vendor)
|
|
.Include(b => b.LineItems.Where(li => !li.IsDeleted))
|
|
.Where(b => !b.IsDeleted);
|
|
|
|
if (statusFilter == "Unpaid")
|
|
query = query.Where(b => b.Status == BillStatus.Open || b.Status == BillStatus.PartiallyPaid);
|
|
else if (statusFilter == "Overdue")
|
|
query = query.Where(b => b.Status != BillStatus.Paid && b.Status != BillStatus.Voided &&
|
|
b.DueDate.HasValue && b.DueDate.Value.Date < DateTime.Today);
|
|
|
|
if (!string.IsNullOrEmpty(searchTerm))
|
|
{
|
|
var term = searchTerm;
|
|
query = query.Where(b =>
|
|
b.BillNumber.Contains(term) ||
|
|
b.Vendor.CompanyName.Contains(term) ||
|
|
(b.VendorInvoiceNumber != null && b.VendorInvoiceNumber.Contains(term)) ||
|
|
(b.Memo != null && b.Memo.Contains(term)) ||
|
|
b.LineItems.Any(li => li.Description.Contains(term)) ||
|
|
(searchAmount.HasValue && (b.Total == searchAmount.Value || b.AmountPaid == searchAmount.Value)));
|
|
}
|
|
|
|
return await query.OrderByDescending(b => b.BillDate).ToListAsync();
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<string?> GetLastBillNumberAsync(string prefix)
|
|
{
|
|
return await _context.Bills
|
|
.IgnoreQueryFilters()
|
|
.Where(b => b.BillNumber.StartsWith(prefix))
|
|
.OrderByDescending(b => b.BillNumber)
|
|
.Select(b => b.BillNumber)
|
|
.FirstOrDefaultAsync();
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<string?> GetLastPaymentNumberAsync(string prefix)
|
|
{
|
|
return await _context.BillPayments
|
|
.IgnoreQueryFilters()
|
|
.Where(p => p.PaymentNumber.StartsWith(prefix))
|
|
.OrderByDescending(p => p.PaymentNumber)
|
|
.Select(p => p.PaymentNumber)
|
|
.FirstOrDefaultAsync();
|
|
}
|
|
}
|