Adding
This commit is contained in:
+27
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+210
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+120
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user