This commit is contained in:
Zeeshaun
2026-03-17 08:54:34 -05:00
parent 64856c640e
commit cdcba54aa4
330 changed files with 54110 additions and 0 deletions
@@ -0,0 +1,27 @@
namespace ReserveManagementSystemApi.Helpers
{
public static class BatchHelper
{
public static IEnumerable<IEnumerable<TSource>> CreateBatch <TSource>(
List<TSource> source, int batchSize)
{
var items = new TSource[batchSize];
var count = 0;
foreach (var item in source)
{
items[count++] = item;
if (count == batchSize)
{
yield return items;
items = new TSource[batchSize];
count = 0;
}
}
if (count > 0)
{
yield return items.Take(count);
}
}
}
}
@@ -0,0 +1,56 @@
using ReserveManagementSystemLib.Models;
namespace ReserveManagementSystemApi.Helpers
{
public class BoatLoanCalculationHelper
{
private LoanReserve loanReserve = new LoanReserve();
public BoatLoanCalculationHelper()
{
}
public LoanReserve CalculateStandardMarkup(CalculationConfig cc)
{
var markup = cc.LoanData().ContractRate - cc.LoanData().BuyRate;
loanReserve.ReserveTypeMessage = "Standard Reserve";
switch (markup)
{
case decimal d when (d >= (decimal)0.00 && d <= (decimal)0.49):
loanReserve.ReserveAmount = cc.LoanData().LoanAmount * (decimal).01;
break;
case decimal d when (d >= (decimal)0.50 && d <= (decimal)0.74):
loanReserve.ReserveAmount = cc.LoanData().LoanAmount * (decimal).02;
break;
case decimal d when (d >= (decimal)0.75 && d <= (decimal)0.99):
loanReserve.ReserveAmount = cc.LoanData().LoanAmount * (decimal).03;
break;
case decimal d when (d >= (decimal)1.00 && d <= (decimal)1.49):
loanReserve.ReserveAmount = cc.LoanData().LoanAmount * (decimal).04;
break;
case decimal d when (d >= (decimal)1.50 && d <= (decimal)1.99):
loanReserve.ReserveAmount = cc.LoanData().LoanAmount * (decimal).05;
break;
case decimal d when (d == (decimal)2.00):
loanReserve.ReserveAmount = cc.LoanData().LoanAmount * (decimal).06;
break;
case decimal d when (d > (decimal)2.00):
loanReserve.ReserveAmount = cc.LoanData().LoanAmount * (decimal).06;
loanReserve.ReserveTypeMessage = "Standard Reserve - Exceeds Max Markup";
break;
default:
loanReserve.ReserveAmount = 0;
loanReserve.ReserveTypeMessage = "No Reserve";
break;
}
return loanReserve;
}
internal DateTime GetLastChargebackDate (DateTime firstPmtDate, int numOfChargebackPayments)
{
return firstPmtDate.AddMonths(numOfChargebackPayments - 1);
}
}
}
@@ -0,0 +1,210 @@
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.IndirectLoan;
using ReserveManagementSystemApi.Models;
using ReserveManagementSystemLib.Models;
namespace ReserveManagementSystemApi.Helpers
{
public class ImportHelper
{
private string _firstName;
private string _middleInitial;
private const double MonthInDays = 30.4375;
public ImportHelper()
{
}
public List<Loan> TransformNewLoan(List<Models.ImportNewLoan> iImportLoans, int iImportId)
{
var result = new List<Loan>();
foreach (var iLoan in iImportLoans)
{
Loan loan = new Loan();
loan.ImportId = iImportId;
loan.MemberNumber = iLoan.MemberNumber;
loan.LoanNumber = iLoan.LoanNumber;
SplitFirstMiddleName(iLoan.FirstAndMiddleName);
loan.MemberFirstName = _firstName?.ToUpper();
loan.MemberInitial = _middleInitial?.ToUpper();
loan.MemberLastName = iLoan.LastName?.ToUpper();
loan.DealerOrganizationNumber = iLoan.DealerOrganizationNumber;
loan.LoanDate = iLoan.LoanDate;
loan.PostedDate = iLoan.PostedDate;
loan.FirstPmtDate = iLoan.FirstPmtDate;
loan.FinalPmtDate = iLoan.FinalPmtDate;
loan.LoanAmount = iLoan.LoanAmount;
loan.BuyRate = Math.Round(iLoan.BuyRate, 3, MidpointRounding.AwayFromZero);
loan.ContractRate = Math.Round(iLoan.ContractRate, 3, MidpointRounding.AwayFromZero);
loan.MonthlyPmt = iLoan.MonthlyPmt;
loan.LoanTypeId = iLoan.LoanType;
loan.ChargeBack = null;
loan.PaidLoanDate = null;
loan.ApplicationId = iLoan.ApplicationId;
loan.AccountType = iLoan.AccountType;
loan.Gap = !string.IsNullOrEmpty(iLoan.Gap) && Convert.ToBoolean(iLoan.Gap);
loan.Warranty = !string.IsNullOrEmpty(iLoan.Warranty) && Convert.ToBoolean(iLoan.Warranty);
loan.CreditLife = !string.IsNullOrEmpty(iLoan.CreditLife) && Convert.ToBoolean(iLoan.CreditLife);
loan.CreditDisability = !string.IsNullOrEmpty(iLoan.CreditDisability) && Convert.ToBoolean(iLoan.CreditDisability);
loan.Mbp = !string.IsNullOrEmpty(iLoan.Mbp) && Convert.ToBoolean(iLoan.Mbp);
loan.Term = (int)Math.Round(Convert.ToDecimal(iLoan.OriginalTermInDays) / (decimal)MonthInDays, 0);
Vehicle vehicle = new Vehicle();
vehicle.VINNumber = !string.IsNullOrEmpty(iLoan.VINNumber) ? iLoan.VINNumber : null;
vehicle.Make = iLoan.Make;
vehicle.Model = iLoan.Model;
vehicle.Year = iLoan.Year;
vehicle.Mileage = ValidateMileage(iLoan.Mileage);
vehicle.Color = iLoan.Color;
loan.Vehicle = vehicle;
result.Add(loan);
}
return result;
}
public List<Loan> TransformLoanFromDNA(List<IndirectLoanDetail> importLoans, int iImportId)
{
var result = new List<Loan>();
if (!importLoans.Any())
{
return result;
}
foreach (var iLoan in importLoans)
{
Loan loan = new Loan
{
ImportId = iImportId,
MemberNumber = iLoan.MemberNumber,
LoanNumber = iLoan.LoanNumber,
MemberFirstName = iLoan.MemberFirstName?.ToUpper(),
MemberInitial = iLoan.MemberInitial?.ToUpper(),
MemberLastName = iLoan.MemberLastName?.ToUpper(),
DealerOrganizationNumber = (!String.IsNullOrWhiteSpace(iLoan.DealerOrganizationNumber)) ? iLoan.DealerOrganizationNumber : string.Empty,
LoanDate = iLoan.LoanDate,
FirstPmtDate = iLoan.FirstPmtDate,
FinalPmtDate = iLoan.FinalPmtDate,
LoanAmount = iLoan.LoanAmount,
BuyRate = (iLoan.BuyRate != 0) ? Math.Round(iLoan.BuyRate, 3, MidpointRounding.AwayFromZero) : 0,
ContractRate = Math.Round(iLoan.ContractRate, 3, MidpointRounding.AwayFromZero),
MonthlyPmt = iLoan.MonthlyPmt,
LoanTypeId = iLoan.LoanType,
ApplicationId = iLoan.ApplicationId,
Gap = iLoan.GAP,
Warranty = iLoan.Warranty,
CreditLife = iLoan.CreditLife,
CreditDisability = iLoan.CreditDisability,
Mbp = iLoan.Mbp,
AccountType = iLoan.AccountType,
PaidLoanDate = iLoan.PaidLoanDate,
Term = (int)Math.Round(Convert.ToDecimal(iLoan.OriginalTermInDays) / (decimal)MonthInDays, 0)
};
if (iLoan.PostedDate == DateTime.MinValue)
{
loan.PostedDate = iLoan.LoanDate;
}
else
{
loan.PostedDate = iLoan.PostedDate;
}
loan.Vehicle = new Vehicle
{
VINNumber = !string.IsNullOrEmpty(iLoan.Vin) ? iLoan.Vin : null,
Make = iLoan.Make,
Model = iLoan.Model,
Year = iLoan.Year.ToString(),
Mileage = ValidateMileage(iLoan.Mileage.ToString()),
Color = iLoan.Color
};
loan.Dealer = new Dealer
{
DealerCode = (!String.IsNullOrWhiteSpace(iLoan.DealerCode)) && (iLoan.DealerCode.Length <= 4) ? iLoan.DealerCode : string.Empty,
Name = (!String.IsNullOrWhiteSpace(iLoan.DealerName)) ? iLoan.DealerName : string.Empty,
DealerAccountNumber = (!String.IsNullOrWhiteSpace(iLoan.DealerAccountNumber)) ? iLoan.DealerAccountNumber : string.Empty,
DealerOrganizationNumber = (!String.IsNullOrWhiteSpace(iLoan.DealerOrganizationNumber)) ? iLoan.DealerOrganizationNumber : string.Empty
};
result.Add(loan);
}
return result;
}
public List<Loan> TransformBoatLoan(List<ImportBoatLoan> importLoans)
{
var result = new List<Loan>();
if (!importLoans.Any())
{
return result;
}
foreach (var iLoan in importLoans)
{
Loan loan = new Loan
{
LoanNumber = iLoan.LoanNumber,
ReserveAmount = (!String.IsNullOrWhiteSpace(iLoan.IsChargeback) && iLoan.IsChargeback.ToUpper() == "FALSE") ? iLoan.Amount : 0,
ChargeBack = (!String.IsNullOrWhiteSpace(iLoan.IsChargeback) && iLoan.IsChargeback.ToUpper() == "TRUE") ? iLoan.Amount : 0,
Adjustment = (!String.IsNullOrWhiteSpace(iLoan.IsAdjustment) && iLoan.IsAdjustment.ToUpper() == "TRUE") ? iLoan.Amount : 0,
AccountType = iLoan.AccountType
};
loan.Dealer = new Dealer
{
DealerAccountNumber = iLoan.DealerAccountNumber
};
result.Add(loan);
}
return result;
}
private double ValidateMileage(string mileage)
{
double convertedMileage;
if (double.TryParse(mileage, out convertedMileage))
{
return convertedMileage;
}
return convertedMileage;
}
public IEnumerable<Loan> TransformClosedLoans(List<ClosedIndirectLoan> importLoans, int importId)
{
return importLoans.Select(x => new Loan
{
ImportId = importId,
LoanNumber = x.LoanNumber,
PaidLoanDate = x.PaidLoanDate
//will update LoanStatus when saving
});
}
private void SplitFirstMiddleName(string name)
{
//initial first name last name rules with first name character max length set in DB as 20, and middle initial max as 1
_middleInitial = String.Empty;
_firstName = name;
string[] names = name.Trim().Split(" ");
if (names != null && names.Length > 1) //when true there is a middle initial
{
_firstName = _firstName.Substring(0, name.Length - names.Last().Length).Trim();
_middleInitial = names.Last().Substring(0, 1);
}
else
{
_firstName = name; //no middle initial
}
}
}
}
@@ -0,0 +1,120 @@
using ReserveManagementSystemLib.Models;
namespace ReserveManagementSystemApi.Helpers
{
public class LoanCalculationHelper
{
private decimal _daysInterest;
private LoanReserve loanReserve = new LoanReserve();
public LoanCalculationHelper()
{
}
public LoanReserve CalculateBuyDown(CalculationConfig cc)
{
// Case - Buy down Below Threshold where difference in rates is less than or equal to 0.25 percent
if (cc.BuydownRateDifference() <= cc.NoReserveThreshold()) //we already know it's positive
{
loanReserve.ReserveAmount = 0;
loanReserve.ReserveTypeMessage = "No Reserve";
loanReserve.FlatFeePaid = false;
return loanReserve;
}
// Case - This is a regular Buy Down
_daysInterest = cc.BuydownRateDifference() / 100 * cc.DaysToFirstPmt() * cc.LoanData().LoanAmount /
365 * (decimal)Math.Pow(1 + (double)cc.LoanData().ContractRate / 100, (double)cc.LoanData().Term / 12);
loanReserve.ReserveAmount = -(cc.BuyFinanceCharge - cc.ContractFinanceCharge + _daysInterest);
loanReserve.ReserveTypeMessage = "Buy Down Reserve";
loanReserve.FlatFeePaid = false;
return loanReserve;
}
public LoanReserve CalculateNoMarkup(CalculationConfig cc)
{
// Case - Contract rate is equal to the Buy rate
_daysInterest = cc.StdRate() * cc.DaysToFirstPmt() * cc.LoanData().LoanAmount /
365 * (decimal)Math.Pow(1 + (double)cc.LoanData().ContractRate / 100, (double)cc.LoanData().Term / 12);
loanReserve.ReserveAmount = (cc.ContractFinanceCharge - cc.BuyFinanceCharge + _daysInterest);
loanReserve.ReserveTypeMessage = "No Reserve";
loanReserve.FlatFeePaid = false;
return loanReserve;
}
public LoanReserve CalculateStandardMarkup(CalculationConfig cc)
{
// Case - Contract rate is greater than Buy rate
_daysInterest = (1 - cc.ReserveDiscount()/100) * cc.StdRate() / 100 * cc.DaysToFirstPmt() * cc.LoanData().LoanAmount /
365 * (decimal)Math.Pow(1 + (double)cc.LoanData().ContractRate / 100, (double)cc.LoanData().Term / 12);
loanReserve.ReserveAmount = ((1 - cc.ReserveDiscount() / 100) * (cc.ContractFinanceCharge - cc.BuyFinanceCharge) + _daysInterest);
if ((double)cc.StdRate() <= 2.5)
{
loanReserve.ReserveTypeMessage = "Standard Reserve";
}
else
{
loanReserve.ReserveTypeMessage = "Standard Reserve - Exceeds Max Markup";
}
return loanReserve;
}
public LoanReserve AssignFlatFee(LoanReserve loanReserve, CalculationConfig cc)
{
loanReserve.FlatFeePaid = false;
if (loanReserve.ReserveAmount < (cc.FlatFeePercent() / 100 * cc._loanData.LoanAmount * (1 - cc.ReserveDiscount() / 100)))
{
loanReserve.ReserveAmount = (cc.FlatFeePercent() / 100 * cc._loanData.LoanAmount * (1 - cc.ReserveDiscount() / 100));
loanReserve.ReserveTypeMessage = "Flat Fee Reserve";
loanReserve.FlatFeePaid = true;
}
return loanReserve;
}
public decimal FinanceCharge(int term, decimal loanAmount, decimal rate)
{
if (rate == 0) { return 0; }
double paymentRate = (double)rate / (double)1200;
decimal rateFactor = (decimal)Math.Pow((1 + paymentRate), (double)term);
return (loanAmount * term * rate / 1200 * rateFactor) / (rateFactor - 1) - loanAmount;
}
internal DateTime GetLastChargebackDate(DateTime loanDate, DateTime firstPmtDate, int numOfChargebackPayments, Int16? numOfChargebackDays)
{
// in rare cases that date from loan date is most recent, check table values and compare between loan date vs. first payment date
int result = DateTime.Compare(loanDate.AddDays((Double)numOfChargebackDays), firstPmtDate.AddMonths(numOfChargebackPayments - 1));
if (result > 0)
{
return loanDate.AddDays((Double)numOfChargebackDays); //Loan Date is most recent
}
return firstPmtDate.AddMonths(numOfChargebackPayments - 1);
}
internal decimal CalculateChargeback(decimal reserve, int term, int remainingMonths)
{
return reserve * MonthFactor(remainingMonths) / MonthFactor(term);
}
private decimal MonthFactor(int numberOfMonths)
{
return numberOfMonths * (numberOfMonths + 1) / 2;
}
public int GetRemainingMonths(Loan loanData)
{
if (loanData.PaidLoanDate >= loanData.FinalPmtDate)
return 0;
var monthsOccurred = (loanData.PaidLoanDate.Value - loanData.FirstPmtDate).TotalDays / (365) * 12 + 1;
var remainingMonths = (int)(loanData.Term - Math.Round((decimal)monthsOccurred, 0));
return remainingMonths;
}
}
}