using System; using System.Collections.Generic; using System.Linq; using LCU.API.Collections.RepoApi.Domain.FloorPricing; using LCU.API.Collections.RepoApi.Domain.FloorPricing.Strategies; using LCU.API.Collections.RepoApi.Exceptions; using LCU.Shared.Collections.RepoApiLib.Models; using LCU.Shared.Collections.RepoApiLib.WebServices.NADA; using Serilog; namespace LCU.API.Collections.RepoApi.Services { public class FloorPricingService : IFloorPricingService { private readonly IFloorPricingStrategyFactory _floorFloorPricingStrategyFactory; private readonly IImsAutoFileDataService _imsAutoFileDataService; private readonly IVehicleFloorPricingParametersService _vehicleFloorPricingParametersService; private readonly ICollateralValueService _collateralValueService; public FloorPricingService( IFloorPricingStrategyFactory floorFloorPricingStrategyFactory, IVehicleFloorPricingParametersService vehicleFloorPricingParametersService, IImsAutoFileDataService imsAutoFileDataService, ICollateralValueService collateralValueService) { _floorFloorPricingStrategyFactory = floorFloorPricingStrategyFactory; _vehicleFloorPricingParametersService = vehicleFloorPricingParametersService; _imsAutoFileDataService = imsAutoFileDataService; _collateralValueService = collateralValueService; } public FloorPriceCalculationResultSet DetermineFloorPrice(int auctionAssignmentId) { CollateralValuation collateralValuation = new CollateralValuation { }; ImsAutoFileData imsAutoFileData = new ImsAutoFileData { }; var floorPricingParams = _vehicleFloorPricingParametersService.ListAll().GetAwaiter().GetResult(); try { imsAutoFileData = _imsAutoFileDataService.GetByAuctionAssignmentId(auctionAssignmentId).GetAwaiter().GetResult(); collateralValuation = GetCollateralValuation(imsAutoFileData.VIN, imsAutoFileData.StatedMileage ?? 0, 0); } catch (Exception ex) { Log.Error(ex, $"Error when trying to Determine Floor Price for auctionAssignment with id: ${auctionAssignmentId}"); } FloorPriceCalculationParams fpcParams = new FloorPriceCalculationParams() { VehicleFloorPricingParameters = floorPricingParams, ImsAutoFileData = imsAutoFileData, CollateralValuation = collateralValuation }; var prices = GetCalculatedFloorPrices(fpcParams); var price = SelectBestFloorPrice(prices); var floorPriceValuesUsed = PopulateFloorPriceValuesUsed(auctionAssignmentId, fpcParams, prices, price); FloorPriceCalculationResultSet strategicResultSet = new FloorPriceCalculationResultSet { }; strategicResultSet.AllResults = prices; strategicResultSet.PrimaryResult = price; strategicResultSet.FloorPriceValuesUsed = floorPriceValuesUsed; return strategicResultSet; } public CollateralValuation GetCollateralValuation(string VIN, int StatedMileage, int vehichleTypeKey) { CollateralValuation collateralValuation = new CollateralValuation { }; try { collateralValuation = _collateralValueService.GetCollateralValue(VIN, StatedMileage, vehichleTypeKey); } catch (Exception ex) { if (ex.Message.Contains("license")) { Log.Error(ex, "Your collateral value service license may be invalid/expired, please notify the collections department administration."); } Log.Error(ex, "NADA ERROR when getting Collateral Value"); } return collateralValuation; } public IReadOnlyCollection GetCalculatedFloorPrices(FloorPriceCalculationParams fpcParams) { IReadOnlyCollection strategies = _floorFloorPricingStrategyFactory.GetFloorPricingStrategies(); List calculationResults = new List(); foreach (var floorPricingStrategy in strategies) { calculationResults.Add(floorPricingStrategy.CalculateFloorPrice(fpcParams)); } return calculationResults; } public FloorPriceCalculationResult SelectBestFloorPrice(IReadOnlyCollection results) { var successWeight = -1; FloorPriceCalculationResult successResult = null; foreach (var result in results) { if (result.ResultWeight > successWeight && result.Success) { successWeight = result.ResultWeight; successResult = result; } } if (successResult == null) { return new FloorPriceCalculationResult() { ResultWeight = -1, Success = false, StrategyName = "Manual", FloorPrice = -1 }; } return successResult; } public FloorPriceValuesUsed PopulateFloorPriceValuesUsed(int auctionAssignmentId, FloorPriceCalculationParams fpcParams, IReadOnlyCollection prices, FloorPriceCalculationResult bestPrice) { var result = new FloorPriceValuesUsed { AuctionAssignmentId = auctionAssignmentId, RepoId = fpcParams.ImsAutoFileData.RepoId, CollateralValuation = fpcParams.CollateralValuation }; result.AuctionGuideBookPrice = fpcParams.ImsAutoFileData.AuctionGuideBookPrice; var autoImsResult = prices.FirstOrDefault(x => x.StrategyName.Equals(typeof(AutoImsSuggestedValue).FullName)); result.WasAuctionGuideBookPriceUsed = autoImsResult != null && autoImsResult.Success && autoImsResult.FloorPrice == bestPrice.FloorPrice; var nadaMmrResult = prices.FirstOrDefault(x => x.StrategyName.Equals(typeof(NadaMmrConditionValue).FullName)); result.MMRNationalAdjustedPrice = fpcParams.ImsAutoFileData.MMRNationalAdjustedPrice; result.MMRRegionalAdjustedPrice = fpcParams.ImsAutoFileData.MMRRegionalAdjustedPrice; result.NADALowAdjustedAuctionValue = fpcParams.CollateralValuation.LowAdjustedAuctionValue; result.NADAAverageAdjustedAuctionValue = fpcParams.CollateralValuation.AverageAdjustedAuctionValue; result.NADAHighAdjustedAuctionValue = fpcParams.CollateralValuation.HighAdjustedAuctionValue; result.Condition = fpcParams.ImsAutoFileData.ApprovedVehicleGrade ?? fpcParams.ImsAutoFileData.VehicleGrade; if (result.Condition == null || result.Condition <= 0) { return result; } var vfpParams = Enumerable.First(Enumerable.Where(fpcParams.VehicleFloorPricingParameters, x => result.Condition >= x.LowCondition && result.Condition <= x.HighCondition)); result.LowParam = vfpParams.LowCondition; result.HighParam = vfpParams.HighCondition; result.PercentageOf = vfpParams.PercentageOf; var hasMmrPrice = fpcParams.ImsAutoFileData.MMRNationalAdjustedPrice != null || fpcParams.ImsAutoFileData.MMRRegionalAdjustedPrice != null; result.WasAuctionGuideBookPriceUsed = autoImsResult != null && autoImsResult.Success && autoImsResult.StrategyName == bestPrice.StrategyName || (!hasMmrPrice && autoImsResult.FloorPrice > 0); result.WasMMRNationalAdjustedPriceUsed = nadaMmrResult != null && nadaMmrResult.Success && vfpParams.MMRAdjustedValue.ToLower().StartsWith("national") && hasMmrPrice; result.WasMMRRegionalAdjustedPriceUsed = nadaMmrResult != null && nadaMmrResult.Success && vfpParams.MMRAdjustedValue.ToLower().StartsWith("regional") && hasMmrPrice; result.WasNADALowAdjustedAuctionValueUsed = nadaMmrResult != null && nadaMmrResult.Success && vfpParams.NADAFirstValue.ToLower().StartsWith("low") || vfpParams.NADASecondValue.ToLower().StartsWith("low"); result.WasNADAAverageAdjustedAuctionValueUsed = nadaMmrResult != null && nadaMmrResult.Success && vfpParams.NADAFirstValue.ToLower().StartsWith("avg") || vfpParams.NADASecondValue.ToLower().StartsWith("avg"); result.WasNADAHighAdjustedAuctionValueUsed = nadaMmrResult != null && nadaMmrResult.Success && vfpParams.NADAFirstValue.ToLower().StartsWith("high") || vfpParams.NADASecondValue.ToLower().StartsWith("high"); return result; } } }