This commit is contained in:
Zeeshaun
2026-04-20 14:47:24 -05:00
parent 89057eceea
commit 8b3ea92501
485 changed files with 71042 additions and 0 deletions
@@ -0,0 +1,21 @@
using System.Collections.Generic;
using LCU.API.Collections.RepoApi.Domain.FloorPricing.Strategies;
namespace LCU.API.Collections.RepoApi.Domain.FloorPricing
{
public class FloorPricingStrategyFactory : IFloorPricingStrategyFactory
{
public FloorPricingStrategyFactory()
{
}
public IReadOnlyCollection<IFloorPricingStrategy> GetFloorPricingStrategies()
{
return new List<IFloorPricingStrategy>()
{
new AutoImsSuggestedValue(),
new NadaMmrConditionValue()
};
}
}
}
@@ -0,0 +1,13 @@
using LCU.Shared.Collections.RepoApiLib.Models;
namespace LCU.API.Collections.RepoApi.Domain.FloorPricing
{
public interface IFloorPricingStrategy
{
FloorPriceCalculationResult CalculateFloorPrice(FloorPriceCalculationParams fpcParams);
int GetStrategyWeight();
// Requirements and Qualifications
}
}
@@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace LCU.API.Collections.RepoApi.Domain.FloorPricing
{
public interface IFloorPricingStrategyFactory
{
IReadOnlyCollection<IFloorPricingStrategy> GetFloorPricingStrategies();
}
}
@@ -0,0 +1,43 @@
using System;
using LCU.Shared.Collections.RepoApiLib.Models;
namespace LCU.API.Collections.RepoApi.Domain.FloorPricing.Strategies
{
/**
* This strategy uses the suggested price from the ImsAutoFileData entry for the auction.
*/
public class AutoImsSuggestedValue : IFloorPricingStrategy
{
public AutoImsSuggestedValue() { }
public FloorPriceCalculationResult CalculateFloorPrice(FloorPriceCalculationParams fpcParams)
{
var result = new FloorPriceCalculationResult()
{
StrategyName = this.GetType().FullName,
Success = false
};
if (fpcParams?.ImsAutoFileData?.AuctionGuideBookPrice != null)
{
// Price must be rounded to nearest $5 per business.
var inputPrice = (double)(fpcParams.ImsAutoFileData.AuctionGuideBookPrice ?? 0);
result.FloorPrice = (decimal) (Math.Round( inputPrice / 5.0) * 5);
result.Success = result.FloorPrice > 0;
result.FailureReason = result.Success ? "" : "Failed attempt to use auction guide book price.";
}
else
{
result.Success = false;
result.FailureReason = "Auction Guide Book Price missing.";
}
return result;
}
public int GetStrategyWeight()
{
return 0; // This is NOT the preferred strategy.
}
}
}
@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using LCU.Shared.Collections.RepoApiLib.Models;
using LCU.Shared.Collections.RepoApiLib.WebServices.NADA;
using Microsoft.EntityFrameworkCore.Internal;
using Enumerable = System.Linq.Enumerable;
namespace LCU.API.Collections.RepoApi.Domain.FloorPricing.Strategies
{
/**
* This strategy uses the AutoIms MMR values, the values from Nada, and the condition from AutoIms along
* with a specific formula, to calculate a floor.
*/
public class NadaMmrConditionValue : IFloorPricingStrategy
{
public FloorPriceCalculationResult CalculateFloorPrice(FloorPriceCalculationParams fpcParams)
{
var result = new FloorPriceCalculationResult()
{
StrategyName = this.GetType().FullName,
Success = false,
ResultWeight = -1
};
if (fpcParams?.CollateralValuation == null || fpcParams?.ImsAutoFileData == null ||
fpcParams?.VehicleFloorPricingParameters == null
|| fpcParams?.VehicleFloorPricingParameters?.Any() == false)
{
// May want to log here, or set a reason code on the result.
result.FailureReason = "Missing ImsAuto File, Pricing Parameters, or Collateral Valuation";
return result;
}
// 1. use condition to find the correct params.
// + VehicleDemicalGradeCode is ignored, ApprovedVehicleGrade is preferred, and Vehicle Grade is the fallback.
var condition = fpcParams.ImsAutoFileData.ApprovedVehicleGrade ?? fpcParams.ImsAutoFileData.VehicleGrade;
if (condition <= 0 || condition == null)
{
result.FailureReason = "No Condition In AutoIMS File Data";
return result;
}
// 2. Get the matching floor pricing calculation row.
var floorPricing = Enumerable.First(Enumerable.Where(fpcParams.VehicleFloorPricingParameters,
x => condition >= x.LowCondition && condition <= x.HighCondition));
// 3. Get the floor pricing params based on matching condition.
var mmrValue = GetMMRValueByParam(floorPricing.MMRAdjustedValue, fpcParams.ImsAutoFileData,
fpcParams.ImsAutoFileData.AuctionGuideBookPrice ?? 0);
List<Decimal> nadaValues = new List<decimal>();
nadaValues.Add(GetNadaValueByParam(floorPricing.NADAFirstValue, fpcParams.CollateralValuation));
nadaValues.Add(GetNadaValueByParam(floorPricing.NADASecondValue, fpcParams.CollateralValuation));
bool onlyZeroNadaValues = nadaValues.TrueForAll(x => x == 0);
if (fpcParams.CollateralValuation.Year <= (DateTime.Now.AddYears(-7).Year) || onlyZeroNadaValues)
{
nadaValues.Add(fpcParams.CollateralValuation.TradeIn);
onlyZeroNadaValues = nadaValues.TrueForAll(x => x == 0);
}
// If there are no NADA or MMR prices, fail the strategy
if (onlyZeroNadaValues && (mmrValue == 0 || mmrValue == fpcParams.ImsAutoFileData.AuctionGuideBookPrice))
{
result.FailureReason = "No NADA or MMR prices returned";
return result;
}
// 4. Run the formula
var nadaValue = GetNadaAvgValue(nadaValues);
var divisor = mmrValue == 0 || nadaValue == 0
? 1
: 2;
var baseResult = (mmrValue + nadaValue) / divisor;
baseResult = (baseResult * floorPricing.PercentageOf) / 100;
baseResult = Math.Round(baseResult / 5.0m) * 5;
result.FloorPrice = baseResult;
result.Success = true;
result.ResultWeight = GetStrategyWeight();
return result;
}
public decimal GetNadaAvgValue(List<Decimal> nadaValues)
{
Decimal aggregateValue = 0;
int valueCount = 0;
Decimal aggregateAvgValue = 0;
if (nadaValues.Count() > 0)
{
foreach (var nadaVal in nadaValues)
{
if (nadaVal > 0)
{
aggregateValue += nadaVal;
valueCount++;
}
}
aggregateAvgValue = aggregateValue / valueCount;
}
return aggregateAvgValue;
}
private decimal GetNadaValueByParam(string floorPricingNadaFirstValue,
CollateralValuation fpcParamsCollateralValuation)
{
if (floorPricingNadaFirstValue.ToLower().StartsWith("low"))
{
return fpcParamsCollateralValuation.LowAdjustedAuctionValue;
}
if (floorPricingNadaFirstValue.ToLower().StartsWith("avg"))
{
return fpcParamsCollateralValuation.AverageAdjustedAuctionValue;
}
return fpcParamsCollateralValuation.HighAdjustedAuctionValue;
}
private decimal GetMMRValueByParam(string floorPricingMmrValue, ImsAutoFileData fpcParamsImsAutoFileData,
decimal defaultValue)
{
if (floorPricingMmrValue.ToLower().StartsWith("regional"))
{
return fpcParamsImsAutoFileData.MMRRegionalAdjustedPrice ?? defaultValue;
}
return fpcParamsImsAutoFileData.MMRNationalAdjustedPrice ?? defaultValue;
}
public int GetStrategyWeight()
{
return 99; // This is the preferred strategy.
}
}
}