using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using LCU.API.Internal.RepoApi.Repos.Exceptions; using LCU.API.Internal.RepoApi.Repos.Extensions; using LCU.API.Internal.RepoApi.Repos.Models; using LCU.API.Internal.RepoApi.Repos.Models.Producer; using LCU.API.Internal.RepoApi.Repos.Models.Results; using LCU.API.Internal.RepoApi.Repos.Persistence; using LCU.Library.Internal.RepoApiModels.Models.Requests; using Microsoft.EntityFrameworkCore; using Serilog; namespace LCU.API.Internal.RepoApi.Repos.Repositories { public class RepoAccountRepository : BaseRepository, IRepoAccountRepository { public RepoAccountRepository(AppDbContext context) : base(context) { } public async Task> ListAsync( List filterAccountNoList, int filterPage, int filterLimit, string status, string auctionHouseId, int? repoCompanyId, bool? onlyOpenAccounts) { var results = new PagedResult(); var skip = (filterPage - 1) * filterLimit; var accounts = _context.RepoAccounts.Select(account => account); // Filter By Repo Ids? if (filterAccountNoList != null && filterAccountNoList.Any()) { accounts = accounts.Where(account => filterAccountNoList.Contains(account.RepoId)); } // Filter By Status? if (!string.IsNullOrEmpty(status)) { accounts = accounts.Where(account => account.Status.ToLower() == status.ToLower()); } // Filter By Auction House? if (!string.IsNullOrEmpty(auctionHouseId)) { accounts = accounts.Join(_context.AuctionAssignments.AsEnumerable(), account => account.RepoId, auction => auction.RepoId, (account, auction) => new { AuctionAssignment = auction, RepoAccount = account }) .Where(joined => joined.AuctionAssignment.IsActive && joined.AuctionAssignment.AuctionId == auctionHouseId) .Select(result => result.RepoAccount); } // Filter By Repo Company? if (repoCompanyId != null) { accounts = accounts.Join(_context.Collaterals.AsEnumerable(), account => account.RepoId, collateral => collateral.RepoId, (account, collateral) => new { RepoAccount = account, Collateral = collateral }) .Join(_context.RepoCompanySelections.AsEnumerable(), accountCollateral => accountCollateral.Collateral.CollateralId, repocompany => repocompany.CollateralId, (accountCollateral, repocompany) => new { accountCollateral.RepoAccount, accountCollateral.Collateral, RepoCompany = repocompany }) .Where(joined => joined.RepoCompany.RepoCompanyId == repoCompanyId) .Select(result => result.RepoAccount); } // Filter Out Closed Accounts? if (onlyOpenAccounts == true) { accounts = accounts.Where(account => !account.DateClosed.HasValue); } accounts = accounts.Distinct(); results.Total = accounts.Count(); results.Items = await accounts.Skip(skip).Take(filterLimit).IncludeAll().ToListAsync(); return results; } public async Task> FindByRepoIdAsync(List filterRepoIdList) { var accounts = await Queryable.OrderByDescending((from account in _context.RepoAccounts where filterRepoIdList.Count == 0 || filterRepoIdList.Contains(account.RepoId.ToString()) select account), x => x.AccountNo).IncludeAll().ToListAsync(); return accounts; } public async Task> ListByAuctionVinAsync(string unformattedVin) { string vin = unformattedVin.Trim().ToUpper(); List repos = await (from account in _context.RepoAccounts join collateral in _context.Collaterals on account.RepoId equals collateral.RepoId where GetFormattedVIN(collateral.Vin) == vin select account).ToListAsync(); return repos; } public async Task> FindByStatusChangeInPeriod( string status, DateTime lowDateTime, DateTime highDateTime, string previousStatus = null) { var repos = await ( from account in _context.RepoAccounts join statusChange in _context.RepoStatusChanges on account.RepoId equals statusChange.RepoId where string.Equals(account.Status, status, StringComparison.CurrentCultureIgnoreCase) && ( previousStatus != null ? string.Equals(statusChange.StatusFrom, previousStatus, StringComparison.CurrentCultureIgnoreCase) : true ) && string.Equals(statusChange.StatusTo, status, StringComparison.CurrentCultureIgnoreCase) && statusChange.ChangedDate >= lowDateTime && statusChange.ChangedDate <= highDateTime select account) .Distinct() .IncludeAll() .ToListAsync(); return repos; } public async Task AddAsync(RepoAccount repo) { var result = await _context.RepoAccounts.AddAsync(repo); return result.Entity; } public async Task FindByIdAsync(int id) { return await Queryable.Where(_context.RepoAccounts, x => x.RepoId == id) .IncludeAll() .FirstOrDefaultAsync(); } public async Task> FindByAccountNoAsync(string accountNo) { var result = await Queryable.Where(_context.RepoAccounts, x => x.AccountNo == accountNo) .IncludeAll().AsNoTracking().ToListAsync(); return result; } public async Task FindByAuctionAssignmentIdAsync(int id) { RepoAccount repo = await ( from account in _context.RepoAccounts join collateral in _context.Collaterals on account.RepoId equals collateral.RepoId join auctionAssignmentToCollateral in _context.AuctionAssignmentToCollaterals on collateral.CollateralId equals auctionAssignmentToCollateral .CollateralId where auctionAssignmentToCollateral.AuctionAssignmentId == id select account).FirstOrDefaultAsync(); return repo; } public static string GetFormattedVIN(string vin) { return vin.Trim().PadLeft(17, '0').ToUpper(); } public void Update(RepoAccount account) { _context.Entry(account).State = EntityState.Modified; _context.RepoAccounts.Update(account); } public void Remove(RepoAccount account) { _context.RepoAccounts.Remove(account); } public async Task> GetItemsForProcessing(IReadOnlyCollection watchStatusList) { var accountList = await _context.RepoAccounts.Where(account => account.DateClosed == null && watchStatusList.Contains(account.Status.ToUpper().Trim())).ToListAsync(); var list = accountList.Select(x => new RepoAccountProcessingRequest() { AccountId = x.ReferenceId.HasValue ? x.ReferenceId.ToString() : "", CaseId = x.ReferenceCaseId.HasValue ? x.ReferenceCaseId.ToString() : "", AccountNo = x.AccountNo }); return list.ToList(); } public async Task> SearchRepoAccounts(string searchPhrase, int maxLimit) { var updatedSearchPhrase = searchPhrase.Trim().ToLower(); var entities = ( from account in _context.RepoAccounts join collateral in _context.Collaterals on account.RepoId equals collateral.RepoId join member in _context.Borrowers on account.RepoId equals member.RepoId where account.AccountNo.ToLower().Contains(updatedSearchPhrase) || collateral.Vin.ToLower().Contains(updatedSearchPhrase) || member.IndividualName.ToLower().Contains(updatedSearchPhrase) select account ); var itemsFound = entities.Count(); if (itemsFound > maxLimit) { throw new MaxItemException(itemsFound); } return await entities .IncludeAll().Distinct() /* distinct because repo can have multiple collaterals, borrowers */ .ToListAsync(); } public async Task> FindByCurrentStatus(string currentStatus) { return await _context.RepoAccounts.Where(repoAccount => repoAccount.Status.ToLower() == currentStatus.ToLower()).IncludeAll().ToListAsync(); } public async Task> GetCurrentAccountsOnHoldAtAuction() { var noHoldStatus = 0; return await ( from repo in _context.RepoAccounts join auctionAssignment in _context.AuctionAssignments on repo.RepoId equals auctionAssignment.RepoId where auctionAssignment.HoldStatus != noHoldStatus && DateTime.Now < auctionAssignment.HoldUntil select repo).Distinct().IncludeAll().ToListAsync(); } } }