using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using LCU.Shared.Collections.RepoApiLib.Extensions; using LCU.Shared.Collections.RepoApiLib.Models; using LCU.Shared.Collections.RepoApiLib.Persistence; using LCU.Shared.Collections.RepoApiLib.Repositories; using LCU.Shared.Collections.RepoApiLib.WebServices.AutoIMS; using Microsoft.EntityFrameworkCore; using Serilog; using AuctionAssignment = LCU.Shared.Collections.RepoApiLib.Models.AuctionAssignment; namespace LCU.API.Collections.RepoApi.Services.AutoIms { public class AuctionProcessorDao : IAuctionProcessorDao { private readonly IImsAutoFileDataRepository _imsAutoFileDataRepository; private readonly IAutoImsWebService _autoImsWebService; private readonly IUnitOfWork _unitOfWork; private readonly AppDbContext _context; private readonly string statusTypeRepo = "REPO"; private readonly string statusTypeSold = "SOLD"; private readonly string statusTypeRedeemed = "REDEEMED"; public AuctionProcessorDao( IImsAutoFileDataRepository imsAutoFileDataRepository, IAutoImsWebService autoImsWebService, AppDbContext context, IUnitOfWork unitOfWork ) { _context = context; _unitOfWork = unitOfWork; _imsAutoFileDataRepository = imsAutoFileDataRepository; _autoImsWebService = autoImsWebService; } public string UpdateAutoImsFromAuctionData(ImsAutoFileData item) { try { WebServiceResponse response = null; Task.Run(async () => { response = await _autoImsWebService.UpdateAuctionIdentifyingValuesAsync( item.AuctionCustomerNo, item.VIN, item.AuctionAssignmentId.ToString()); }).Wait(); return "Updated AutoIMS with Landmark identifiers."; } catch (Exception ex) { Log.Error(ex, "UpdateAutoIMS From Auction Failure"); return "Failure Updating AutoIMS with Landmark identifiers."; } } public static string GetFormattedVin(string vin) { return !string.IsNullOrWhiteSpace(vin) ? vin.Trim().PadLeft(17, '0').ToUpper() : null; } public RepoAccount FindByAuctionCustomerNoAndVinAsync(string auctionCustomerNo, string unformattedVin) { List repos = FindRepoByStatus(auctionCustomerNo, unformattedVin, statusTypeRepo); if (!repos.Any()) { repos = FindRepoByStatus(auctionCustomerNo, unformattedVin, statusTypeSold); } if (!repos.Any()) { repos = FindRepoByStatus(auctionCustomerNo, unformattedVin, statusTypeRedeemed); } /* Currently we cannot error on multiple rows returned because we can have duplicate repos in the database We will need to perform extensive data cleanup before this can be enabled */ // if (repos.Count > 1) // { // throw new Exception($"Multiple Auction Assignments Returned For: AuctionCustomerNo:{auctionCustomerNo} | VIN:{vin}"); // } return repos.FirstOrDefault(); } public ImsAutoFileData UpdateExistingFile(ImsAutoFileData existingAuctionFile, ImsAutoFileData imsAutoFileData) { _context.Entry(existingAuctionFile).CurrentValues.SetValues(imsAutoFileData); imsAutoFileData.DateReceivedFromAutoIMS = existingAuctionFile.DateReceivedFromAutoIMS; imsAutoFileData.CollateralImagePath = _autoImsWebService.GetCollateralImage(imsAutoFileData.ConditionReportLink); _imsAutoFileDataRepository.Update(existingAuctionFile); _unitOfWork.CompleteAsync().GetAwaiter().GetResult(); return imsAutoFileData; } public ImsAutoFileData CreateImsAuctionFileData(ImsAutoFileData imsAutoFileData) { imsAutoFileData.DateReceivedFromAutoIMS = DateTime.Now; imsAutoFileData.CollateralImagePath = _autoImsWebService.GetCollateralImage(imsAutoFileData.ConditionReportLink); Add(imsAutoFileData); _unitOfWork.CompleteAsync().GetAwaiter().GetResult(); return imsAutoFileData; } public void Add(ImsAutoFileData assignment) { _context.ImsAutoFileData.Add(assignment); } public ImsAutoFileData FindByAuctionAssignmentIdAsync(int auctionAssignmentId) { return _context.ImsAutoFileData.AsNoTracking() .FirstOrDefault(x => x.AuctionAssignmentId == auctionAssignmentId); } public ImsAutoFileData GetNonConformingImsFileRecord(string vin, string auctionCustomerNo) { ImsAutoFileData imsAutoFile = null; // Allow for vehicle brought back to auction after sale. it happens! DateTime withinThirtyDays = DateTime.Now.AddDays(-30); imsAutoFile = _context.ImsAutoFileData.AsNoTracking().FirstOrDefault(x => (x.VIN.Trim() == vin && x.AuctionCustomerNo == auctionCustomerNo && (x.SoldDate == null || x.SoldDate >= withinThirtyDays))); return imsAutoFile; } public ImsAutoFileData FindImsAuctionFileData(int auctionAssignmentId, string customerNo, string VIN) { var existingAuctionFile = FindByAuctionAssignmentIdAsync(auctionAssignmentId) ?? GetNonConformingImsFileRecord(VIN, customerNo); return existingAuctionFile; } public AuctionAssignment FindByIdAsync(int id) { return _context.AuctionAssignments.Where(c => c.ID == id).IncludeAll().FirstOrDefault(); } public AuctionAssignment FindByAuctionCustomerNoAndVin(string auctionCustomerNo, string vin) { List auctionAssignments = FindAuctionByStatus(auctionCustomerNo, vin, statusTypeRepo); if(!auctionAssignments.Any()) { auctionAssignments = FindAuctionByStatus(auctionCustomerNo, vin, statusTypeSold); } if (!auctionAssignments.Any()) { auctionAssignments = FindAuctionByStatus(auctionCustomerNo, vin, statusTypeRedeemed); } return auctionAssignments.FirstOrDefault(); } public AuctionAssignment FindAuctionAssignment(ImsAutoFileData item) { var auctionAssignment = /* FindByIdAsync(item.AuctionAssignmentId) this can't be used because old numbers will exist at first. ??*/ FindByAuctionCustomerNoAndVin(item.AuctionCustomerNo, item.VIN); if (auctionAssignment == null) { throw new Exception("Auction assignment not found for Individual/VIN " + item.AuctionCustomerNo); } return auctionAssignment; } public RepoAccount FindRepoForImsAuctionItem(ImsAutoFileData item) { RepoAccount repo = null; // GJF, this can't be used because old numbers will exist at first.... // if (item.AuctionAssignmentId > 0) { // repo = await _repoAccountRepository.FindByAuctionAssignmentIdAsync(item.AuctionAssignmentId); // } repo = FindByAuctionCustomerNoAndVinAsync(item.AuctionCustomerNo, item.VIN); if (repo == null) { throw new Exception("Repo Account not found for Individual/VIN " + item.AuctionCustomerNo); } return repo; } public IReadOnlyCollection ListReadyForFloorPrice() { var temp = (from x in _context.AuctionAssignments where (x.FloorPrice ?? 0) == 0 && x.AutoIMS != null && x.AutoIMS.SoldDate == null && (x.AutoIMS.StatedMileage ?? -1) > 1 && x.AutoIMS.ScheduledSaleDate != null && x.AutoIMS.ScheduledSaleDate > DateTime.Now.Date && x.RedeemedDate == null && ((x.AutoIMS.ApprovedVehicleGrade ?? 0) > 0 || (x.AutoIMS.VehicleGrade ?? 0) > 0) select x).OrderByDescending(x => x.ID); return temp.IncludeAll().ToList(); } private List FindRepoByStatus(string auctionCustomerNo, string unformattedVin, string statusType) { return (from account in _context.RepoAccounts join collateral in _context.Collaterals on account.RepoId equals collateral.RepoId join auctionAssignment in _context.AuctionAssignments on account.RepoId equals auctionAssignment.RepoId where GetFormattedVin(collateral.Vin) == GetFormattedVin(unformattedVin) && (auctionAssignment.AuctionCustomerNo == auctionCustomerNo || string.IsNullOrWhiteSpace(auctionCustomerNo)) && account.Status == statusType select account).ToList(); } private List FindAuctionByStatus(string auctionCustomerNo, string vin, string statusType) { return (from auctionAssignment in _context.AuctionAssignments join account in _context.RepoAccounts on auctionAssignment.RepoId equals account.RepoId join collateral in _context.Collaterals on account.RepoId equals collateral.RepoId where GetFormattedVin(collateral.Vin) == GetFormattedVin(vin) && (auctionAssignment.AuctionCustomerNo == auctionCustomerNo || string.IsNullOrWhiteSpace(auctionCustomerNo)) && account.Status == statusType select auctionAssignment).ToList(); } } }