356 lines
15 KiB
C#
356 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data.SqlClient;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using LCU.API.Collections.RepoApi.Exceptions;
|
|
using LCU.API.Collections.RepoApi.Models;
|
|
using LCU.API.Collections.RepoApi.Models.Filters;
|
|
using LCU.API.Collections.RepoApi.Models.Requests;
|
|
using LCU.Shared.Collections.RepoApiLib.Exceptions;
|
|
using LCU.Shared.Collections.RepoApiLib.Models;
|
|
using LCU.Shared.Collections.RepoApiLib.Models.Producer;
|
|
using LCU.Shared.Collections.RepoApiLib.Models.Results;
|
|
using LCU.Shared.Collections.RepoApiLib.Repositories;
|
|
using Serilog;
|
|
|
|
namespace LCU.API.Collections.RepoApi.Services
|
|
{
|
|
public class RepoAccountService : IRepoAccountService
|
|
{
|
|
private readonly IRepoAccountRepository _repoAccountRepository;
|
|
private readonly IRepoStatusChangeRepository _repoStatusChangeRepository;
|
|
private readonly IRepoManualStatusRepository _repoManualStatusRepository;
|
|
private readonly IUnitOfWork _unitOfWork;
|
|
|
|
public RepoAccountService(
|
|
IRepoAccountRepository repoAccountRepository,
|
|
IRepoStatusChangeRepository repoStatusChangeRepository,
|
|
IRepoManualStatusRepository repoManualStatusRepository,
|
|
IUnitOfWork unitOfWork)
|
|
{
|
|
_repoAccountRepository = repoAccountRepository;
|
|
_repoStatusChangeRepository = repoStatusChangeRepository;
|
|
_repoManualStatusRepository = repoManualStatusRepository;
|
|
_unitOfWork = unitOfWork;
|
|
}
|
|
|
|
public async Task<PagedResult<RepoAccount>> ListAll(PageFilter pageFilter, RepoAccountPostFilter repoAccountFilter)
|
|
{
|
|
try
|
|
{
|
|
return await _repoAccountRepository.ListAsync(
|
|
repoAccountFilter != null ? repoAccountFilter.RepoIdList : new List<int?>(),
|
|
pageFilter.Page,
|
|
pageFilter.Limit,
|
|
repoAccountFilter?.Status,
|
|
repoAccountFilter?.AuctionHouseId,
|
|
repoAccountFilter?.RepoCompanyId,
|
|
repoAccountFilter?.OnlyOpenAccounts);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failure retrieving RepoAccounts");
|
|
throw new ServerErrorException();
|
|
}
|
|
}
|
|
|
|
public async Task<RepoAccount> FindByAuctionAssignmentId(int auctionAssignmentId)
|
|
{
|
|
try
|
|
{
|
|
return await _repoAccountRepository.FindByAuctionAssignmentIdAsync(auctionAssignmentId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failure retrieving RepoAccount");
|
|
throw new ServerErrorException();
|
|
}
|
|
}
|
|
|
|
public async Task<RepoAccount> SaveAsync(RepoAccount repoAccount)
|
|
{
|
|
try
|
|
{
|
|
var newAccount = await _repoAccountRepository.AddAsync(repoAccount);
|
|
RepoStatusChange change = new RepoStatusChange()
|
|
{
|
|
RepoId = newAccount.RepoId,
|
|
ChangedBy = "System",
|
|
StatusFrom = "None",
|
|
StatusTo = repoAccount.Status,
|
|
ChangedDate = DateTime.Now
|
|
};
|
|
await _repoStatusChangeRepository.AddAsync(change);
|
|
await _unitOfWork.CompleteAsync();
|
|
|
|
return repoAccount;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Failure saving Repo Account: {repoAccount}", repoAccount);
|
|
throw new ServerErrorException();
|
|
}
|
|
}
|
|
|
|
public async Task<RepoAccount> Get(int id)
|
|
{
|
|
RepoAccount repoAccount;
|
|
try
|
|
{
|
|
repoAccount = await _repoAccountRepository.FindByIdAsync(id);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Failure retrieving Repo Account with id: {id}");
|
|
throw new ServerErrorException();
|
|
}
|
|
|
|
if (repoAccount == null)
|
|
{
|
|
throw new NotFoundException($" Repo Accounts with id {id} not found.");
|
|
}
|
|
|
|
return repoAccount;
|
|
}
|
|
|
|
public async Task<IReadOnlyCollection<RepoAccount>> GetByAccountNo(string accountNo)
|
|
{
|
|
IReadOnlyCollection<RepoAccount> repoAccounts;
|
|
try
|
|
{
|
|
repoAccounts = await _repoAccountRepository.FindByAccountNoAsync(accountNo);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Failure retrieving Repo Account by accountNo with accountNo: {accountNo}");
|
|
throw new ServerErrorException();
|
|
}
|
|
|
|
if (repoAccounts == null || !repoAccounts.Any())
|
|
{
|
|
throw new NotFoundException($" Repo Accounts with id {accountNo} not found.");
|
|
}
|
|
|
|
return repoAccounts;
|
|
}
|
|
|
|
public async Task<RepoAccount> UpdateAsync(RepoAccount repoAccount, AppUser currentUser)
|
|
{
|
|
var existingRepoAccount = await _repoAccountRepository.FindByIdAsync(repoAccount.RepoId);
|
|
|
|
if (existingRepoAccount == null)
|
|
{
|
|
throw new NotFoundException($"Repo Account with repoId {repoAccount.RepoId} not found.");
|
|
}
|
|
|
|
var originalStatus = existingRepoAccount.Status;
|
|
|
|
existingRepoAccount.AccountLastProcessed = repoAccount.AccountLastProcessed;
|
|
existingRepoAccount.AccountNo = repoAccount.AccountNo;
|
|
existingRepoAccount.AccountTypeCode = repoAccount.AccountTypeCode;
|
|
existingRepoAccount.Balance = repoAccount.Balance;
|
|
existingRepoAccount.Bankruptcy = repoAccount.Bankruptcy;
|
|
existingRepoAccount.Borrowers = repoAccount.Borrowers;
|
|
existingRepoAccount.Branch = repoAccount.Branch;
|
|
// Only one field can change in collaterals when updating the account.
|
|
if (existingRepoAccount.Collaterals != null)
|
|
{
|
|
foreach (var collateral in existingRepoAccount.Collaterals)
|
|
{
|
|
var newCollateral =
|
|
repoAccount.Collaterals.FirstOrDefault(x => x.CollateralId == collateral.CollateralId);
|
|
if (newCollateral != null)
|
|
{
|
|
collateral.RetitledInLandmarkName = newCollateral.RetitledInLandmarkName;
|
|
}
|
|
}
|
|
}
|
|
|
|
// existingRepoAccount.Collaterals = repoAccount.Collaterals; This will fail, save separately.
|
|
existingRepoAccount.Collector = repoAccount.Collector;
|
|
existingRepoAccount.CurrentDelinquentAmount = repoAccount.CurrentDelinquentAmount;
|
|
existingRepoAccount.DateClosed = repoAccount.DateClosed;
|
|
existingRepoAccount.DateFirstDelinquent = repoAccount.DateFirstDelinquent;
|
|
existingRepoAccount.DateFirstIntellect = repoAccount.DateFirstIntellect;
|
|
existingRepoAccount.DaysDelinquent = repoAccount.DaysDelinquent;
|
|
existingRepoAccount.DelinquentAmount = repoAccount.DelinquentAmount;
|
|
existingRepoAccount.DueToPayDate = repoAccount.DueToPayDate;
|
|
existingRepoAccount.LastPaymentDate = repoAccount.LastPaymentDate;
|
|
existingRepoAccount.LoanNo = repoAccount.LoanNo;
|
|
existingRepoAccount.LstPmtAmt = repoAccount.LstPmtAmt;
|
|
existingRepoAccount.ManualRedemptionDate = repoAccount.ManualRedemptionDate;
|
|
existingRepoAccount.MemberNo = repoAccount.MemberNo;
|
|
existingRepoAccount.O4RDate = repoAccount.O4RDate;
|
|
existingRepoAccount.OrigAmount = repoAccount.OrigAmount;
|
|
existingRepoAccount.OrigAccountTypeCode = repoAccount.OrigAccountTypeCode;
|
|
existingRepoAccount.PaidSkipAmount = repoAccount.PaidSkipAmount;
|
|
existingRepoAccount.PrimaryIndividualId = repoAccount.PrimaryIndividualId;
|
|
existingRepoAccount.RedemptionExpiredDate = repoAccount.RedemptionExpiredDate;
|
|
existingRepoAccount.RefundStatus = repoAccount.RefundStatus;
|
|
existingRepoAccount.RequiredPaymentAmount = repoAccount.RequiredPaymentAmount;
|
|
existingRepoAccount.ReferenceId = repoAccount.ReferenceId;
|
|
existingRepoAccount.ReferenceCaseId = repoAccount.ReferenceCaseId;
|
|
existingRepoAccount.ReferenceStatus = repoAccount.ReferenceStatus;
|
|
existingRepoAccount.Status = repoAccount.Status;
|
|
existingRepoAccount.SubStatus = repoAccount.SubStatus;
|
|
existingRepoAccount.WrittenOffDate = repoAccount.WrittenOffDate;
|
|
existingRepoAccount.SixtyPlusCollectorId = repoAccount.SixtyPlusCollectorId;
|
|
|
|
try
|
|
{
|
|
_repoAccountRepository.Update(existingRepoAccount);
|
|
if (originalStatus != repoAccount.Status)
|
|
{
|
|
var change = new RepoStatusChange()
|
|
{
|
|
RepoId = repoAccount.RepoId,
|
|
ChangedBy = currentUser.FirstName + " " + currentUser.LastName,
|
|
StatusFrom = originalStatus,
|
|
StatusTo = repoAccount.Status,
|
|
ChangedDate = DateTime.Now
|
|
};
|
|
await _repoStatusChangeRepository.AddAsync(change);
|
|
}
|
|
await _unitOfWork.CompleteAsync();
|
|
return await _repoAccountRepository.FindByIdAsync(repoAccount.RepoId);
|
|
}
|
|
catch (SqlException ex)
|
|
{
|
|
Log.Error(ex, $"SQL Failure updating Repo Account: {repoAccount}", repoAccount);
|
|
throw new ServerErrorException();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Failure updating Repo Account: {repoAccount}", repoAccount);
|
|
throw new ServerErrorException();
|
|
}
|
|
}
|
|
|
|
public async Task<RepoAccount> DeleteAsync(int id)
|
|
{
|
|
RepoAccount existingRepoAccount;
|
|
try
|
|
{
|
|
existingRepoAccount = await _repoAccountRepository.FindByIdAsync(id);
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
Log.Error(ex, $"Error finding an existing repo to delete with account ID: {id}");
|
|
throw new ServerErrorException();
|
|
}
|
|
|
|
if (existingRepoAccount == null)
|
|
{
|
|
throw new NotFoundException($" Repo Account with id {id} not found.");
|
|
}
|
|
|
|
try
|
|
{
|
|
_repoAccountRepository.Remove(existingRepoAccount);
|
|
await _unitOfWork.CompleteAsync();
|
|
return existingRepoAccount;
|
|
}
|
|
catch (SqlException ex)
|
|
{
|
|
Log.Error(ex, $"SQL Failure deleting Repo Account with id: {id}", id);
|
|
throw new ServerErrorException();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Failure deleting Repo Account with id: {id}", id);
|
|
throw new ServerErrorException();
|
|
}
|
|
}
|
|
|
|
public async Task<IReadOnlyCollection<ProcessingItem>> GetItemsForProcessing()
|
|
{
|
|
try
|
|
{
|
|
var watchStatus = await _repoManualStatusRepository.ListWatchStatusesAsync();
|
|
var repoAccountNos = await _repoAccountRepository.GetItemsForProcessing(watchStatus);
|
|
return repoAccountNos;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, "Failure getting Repo Account Nos for polling");
|
|
throw new ServerErrorException();
|
|
}
|
|
}
|
|
|
|
public async Task<IReadOnlyCollection<RepoAccount>> SearchRepoAccounts(string searchPhrase, int maxAllowedResults)
|
|
{
|
|
try
|
|
{
|
|
var matchedRepoAccounts = await _repoAccountRepository.SearchRepoAccounts(searchPhrase, maxAllowedResults);
|
|
return matchedRepoAccounts;
|
|
}
|
|
catch (MaxItemException ex)
|
|
{
|
|
Log.Error(ex, $"Search Phrase Returned More Items Than Max (${maxAllowedResults}) searchPhrase:{searchPhrase}", searchPhrase);
|
|
throw new MaxItemException(ex.ItemCount);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Failure Searching For Repo Accounts searchPhrase: {searchPhrase}", searchPhrase);
|
|
throw new ServerErrorException();
|
|
}
|
|
}
|
|
|
|
public async Task<RepoAccount> GetNewestOpenAccount(string accountNo)
|
|
{
|
|
IReadOnlyCollection<RepoAccount> repoAccounts;
|
|
try
|
|
{
|
|
repoAccounts = await _repoAccountRepository.FindByAccountNoAsync(accountNo);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error(ex, $"Failure retrieving Repo Account by accountNo with accountNo: {accountNo}");
|
|
throw new ServerErrorException();
|
|
}
|
|
|
|
if (repoAccounts == null || !repoAccounts.Any())
|
|
{
|
|
// You can't throw here, it's not an exception case, there simply isn't an account. (404)
|
|
Log.Debug($" Repo Accounts with id {accountNo} not found.");
|
|
return null;
|
|
}
|
|
|
|
return SelectFirstOpenAccount(repoAccounts);
|
|
}
|
|
|
|
/**
|
|
* Attempts to select the repo account that should be updated. Since we have to go by AccountNo and there
|
|
* may be more than one. Try to return an open account, and log if it detects more than one.
|
|
*/
|
|
public RepoAccount SelectFirstOpenAccount(IReadOnlyCollection<RepoAccount> repoAccounts)
|
|
{
|
|
if (repoAccounts.Count == 1)
|
|
{
|
|
return repoAccounts.First();
|
|
}
|
|
|
|
RepoAccount openAccount = null;
|
|
foreach (var repoAccount in repoAccounts.OrderBy(x => x.RepoId))
|
|
{
|
|
if (repoAccount.DateClosed == null)
|
|
{
|
|
if (openAccount != null)
|
|
{
|
|
Log.Fatal($"Multiple -OPEN- Repos with AccountNo: {openAccount.AccountNo}, {openAccount.RepoId} / {repoAccount.RepoId}");
|
|
return openAccount;
|
|
}
|
|
openAccount = repoAccount;
|
|
}
|
|
}
|
|
|
|
if (openAccount != null)
|
|
{
|
|
return openAccount;
|
|
}
|
|
|
|
return repoAccounts.OrderByDescending(x => x.DateClosed).ToList().FirstOrDefault();
|
|
}
|
|
}
|
|
} |