first commit
This commit is contained in:
+283
@@ -0,0 +1,283 @@
|
||||
using FluentValidation;
|
||||
using Landmark.OLA.Models.Assets;
|
||||
using Landmark.OLA.Models.HomeMortgageDisclosureAct.Validators;
|
||||
using Landmark.OLA.Models.Individuals.Validators;
|
||||
using Landmark.OLA.Models.Loan.Enums;
|
||||
|
||||
namespace Landmark.OLA.Models.Loan.Validators
|
||||
{
|
||||
public class LoanApplicationValidator : AbstractValidator<LoanApplication>
|
||||
{
|
||||
public LoanApplicationValidator()
|
||||
{
|
||||
RuleFor(x => x.PrimaryBorrower).SetValidator(new ApplicantValidator());
|
||||
|
||||
//when primary is married and in a state requiring spouse information
|
||||
When(x =>
|
||||
(x.PrimaryBorrower.IsMarried ?? false) &&
|
||||
(x.PrimaryBorrower.Address?.State.HasValue ?? false) &&
|
||||
ValidationConstants.StatesRequiringSpouseInformation.Contains(x.PrimaryBorrower.Address.State.Value),
|
||||
() =>
|
||||
{
|
||||
//Primary must have spouse data if not married to coapplicant
|
||||
RuleFor(x => x.PrimaryBorrower.HasAnyNonApplicantSpouse()).Equal(true)
|
||||
.Unless(x => x.CoApplicant?.IsMarriedToPrimaryBorrower ?? false)
|
||||
.WithMessage("PrimaryBorrower must include spouse information due to marriage in a community property state.");
|
||||
});
|
||||
|
||||
|
||||
//when coapp is married and in a state requiring spouse information
|
||||
When(x =>
|
||||
(x.CoApplicant?.IsMarried ?? false) &&
|
||||
(x.CoApplicant?.Address?.State.HasValue ?? false) &&
|
||||
ValidationConstants.StatesRequiringSpouseInformation.Contains(x.CoApplicant.Address.State.Value),
|
||||
() =>
|
||||
{
|
||||
//coapp must have spouse data if not married to coapplicant
|
||||
RuleFor(x => x.CoApplicant.HasAnyNonApplicantSpouse()).Equal(true)
|
||||
.Unless(x => x.CoApplicant?.IsMarriedToPrimaryBorrower ?? false)
|
||||
.WithMessage("CoApplicant must include spouse information due to marriage in a community property state.");
|
||||
});
|
||||
|
||||
|
||||
Unless(x => x.CoApplicant is null, () =>
|
||||
{
|
||||
RuleFor(x => x.CoApplicant).SetValidator(new ApplicantValidator());
|
||||
|
||||
When(x => x.CoApplicant.IsMarriedToPrimaryBorrower, () =>
|
||||
{
|
||||
//If the two applicants are married there should be no other spouse information
|
||||
RuleFor(x => x.PrimaryBorrower.NonApplicantSpouse).Null();
|
||||
RuleFor(x => x.PrimaryBorrower.DetailedNonApplicantSpouse).Null();
|
||||
|
||||
RuleFor(x => x.CoApplicant.NonApplicantSpouse).Null();
|
||||
RuleFor(x => x.CoApplicant.DetailedNonApplicantSpouse).Null();
|
||||
});
|
||||
});
|
||||
|
||||
When(x => (x.PrimaryBorrower?.IsMarried ?? false) == false, () =>
|
||||
{
|
||||
RuleFor(x => x.PrimaryBorrower.HasAnyNonApplicantSpouse()).Equal(false)
|
||||
.WithMessage("PrimaryBorrower is set as not married but includes spouse information.");
|
||||
});
|
||||
|
||||
When(x => IsHmdaLoan(x.LoanType), () =>
|
||||
{
|
||||
RuleFor(x => x.PrimaryBorrower.HmdaValues).SetValidator(new HmdaValidator());
|
||||
|
||||
RuleFor(x => x.CoApplicant.HmdaValues).SetValidator(new HmdaValidator())
|
||||
.Unless(x => x.CoApplicant is null);
|
||||
});
|
||||
|
||||
When(x => IsVehicleRequired(x.LoanType), () =>
|
||||
{
|
||||
RuleFor(x => x.Vehicle).NotNull();
|
||||
|
||||
RuleFor(x => x).SetValidator(new VehicleValidator());
|
||||
});
|
||||
|
||||
When(x => IsRealEstateRequired(x.LoanType), () =>
|
||||
{
|
||||
RuleFor(x => x.RealEstate).NotNull();
|
||||
});
|
||||
|
||||
When(x => IsTermRequired(x.LoanType), () =>
|
||||
{
|
||||
RuleFor(x => x.TermLengthInMonths).NotNull();
|
||||
RuleFor(x => x.TermLengthInMonths).Must((x, termLength) => IsValidTermLength(x) == true)
|
||||
.WithMessage("TermLengthInMonths is not set to a valid value for this loan type.");
|
||||
});
|
||||
|
||||
RuleFor(x => x.Purpose).Must((x, purpose) => LoanPurpose.IsValidPurposeForType(x.LoanType, purpose));
|
||||
|
||||
Unless(x => x.LoanType.Value == LoanType.CC_CashBack || x.LoanType.Value == LoanType.CC_Rewards || x.LoanType.Value == LoanType.CC_Secure
|
||||
|| x.LoanType.Value == LoanType.CC_Student, () => {
|
||||
RuleFor(x => x.RequestedAmount).Must((x, requestedAmount) => LoanLimits.IsValidAmountForType(x.LoanType.Value, requestedAmount.Value))
|
||||
.WithMessage("The requested loan amount is outside the limits for this product type.");
|
||||
});
|
||||
|
||||
|
||||
//They actually can, but for now that means something went wrong on the frontend.
|
||||
//To allow vehicle details on preapprovals, simply remove this validation and everything should likely work.
|
||||
RuleFor(x => x.Vehicle).Null().When(x => x.LoanType == LoanType.V_VehiclePreapproval)
|
||||
.WithMessage("Vehicle PreApproval loans cannot include vehicle details");
|
||||
|
||||
When(x => IsClientMessageRequired(x.LoanType), () =>
|
||||
{
|
||||
RuleFor(x => x.ClientMessage).NotNull();
|
||||
RuleFor(x => x.ClientMessage.Trim()).Must((x, clientMessage) => clientMessage.Length >= 5)
|
||||
.WithMessage("Applications for this type of loan must include a client message");
|
||||
});
|
||||
}
|
||||
|
||||
private bool IsValidTermLength(LoanApplication loanApplication)
|
||||
{
|
||||
if ((!loanApplication.LoanType.HasValue) || (!loanApplication.TermLengthInMonths.HasValue))
|
||||
return false;
|
||||
|
||||
List<int> validTermLengths = this.GetValidTermLengthsForLoanType(loanApplication);
|
||||
|
||||
return validTermLengths.Contains(loanApplication.TermLengthInMonths.Value);
|
||||
}
|
||||
|
||||
private List<int> GetValidTermLengthsForLoanType(LoanApplication loanApplication)
|
||||
{
|
||||
return loanApplication.LoanType.Value switch
|
||||
{
|
||||
LoanType.EQ_Mtg_Refi_Express => TermLengths.MortgageRefiExpress,
|
||||
LoanType.EQ_Home_Equity_Fixed => TermLengths.HomeEquity,
|
||||
LoanType.V_VehiclePreapproval => TermLengths.VehiclePreApproval,
|
||||
LoanType.V_Vehicle => GetVehicleTermList(loanApplication.Vehicle),
|
||||
LoanType.EQ_Mfg_Home_With_or_Without_Land or LoanType.T_TrailerMotorhome => GetMfdHomeAndRvTermList(loanApplication.RequestedAmount.Value),
|
||||
LoanType.M_Boat => GetBoatTermList(loanApplication.RequestedAmount.Value),
|
||||
LoanType.P_Powersport => GetPowersportTermList(loanApplication.Vehicle.InitialEstimatedValue.Value),
|
||||
LoanType.S_Signature => GetSignatureTermList(loanApplication.RequestedAmount.Value),
|
||||
LoanType.S_Special => GetSpecialTermList(loanApplication.RequestedAmount.Value),
|
||||
LoanType.CC_CashBack => [],
|
||||
LoanType.CC_Rewards => [],
|
||||
LoanType.CC_Student => [],
|
||||
LoanType.CC_Secure => [],
|
||||
LoanType.EQ_HELOC_Flex => [],
|
||||
_ => [],
|
||||
};
|
||||
}
|
||||
|
||||
private static List<int> GetSignatureTermList(decimal loanAmount)
|
||||
{
|
||||
var applicableKeys = TermLengths.SignatureByAmount.Keys.Where(x => loanAmount >= x);
|
||||
var allowedTerms = new List<int>();
|
||||
foreach (var key in applicableKeys)
|
||||
{
|
||||
allowedTerms.AddRange(TermLengths.SignatureByAmount[key]);
|
||||
}
|
||||
return allowedTerms;
|
||||
}
|
||||
|
||||
|
||||
private static List<int> GetSpecialTermList(decimal loanAmount)
|
||||
{
|
||||
var allowedTerms = new List<int>
|
||||
{
|
||||
36
|
||||
};
|
||||
return allowedTerms;
|
||||
}
|
||||
|
||||
private static List<int> GetMfdHomeAndRvTermList(decimal loanAmount)
|
||||
{
|
||||
var availableTermLengths = new List<int>();
|
||||
|
||||
foreach (var amount in TermLengths.MfdHomeAndRvByAmount.Keys)
|
||||
{
|
||||
if (loanAmount >= amount)
|
||||
{
|
||||
availableTermLengths.AddRange(TermLengths.MfdHomeAndRvByAmount[amount]);
|
||||
}
|
||||
}
|
||||
|
||||
return availableTermLengths;
|
||||
}
|
||||
|
||||
public static List<int> GetVehicleTermList(Vehicle vehicle)
|
||||
{
|
||||
if ((vehicle is null) || (!vehicle.Condition.HasValue) || (!vehicle.Year.HasValue))
|
||||
return [];
|
||||
|
||||
var yearList = TermLengths.TermsByYear;
|
||||
|
||||
int lookupYear = vehicle.Year.Value;
|
||||
|
||||
if (yearList.TryGetValue(lookupYear, out List<int> value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else if (lookupYear >= yearList.First().Key)
|
||||
{
|
||||
return yearList.First().Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return yearList.Last().Value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static List<int> GetBoatTermList(decimal loanAmount)
|
||||
{
|
||||
var applicableKeys = TermLengths.BoatLoansByAmount.Keys.Where(x => loanAmount >= x);
|
||||
|
||||
var allowedTerms = new List<int>();
|
||||
|
||||
foreach (var key in applicableKeys)
|
||||
{
|
||||
allowedTerms.AddRange(TermLengths.BoatLoansByAmount[key]);
|
||||
}
|
||||
|
||||
return allowedTerms;
|
||||
}
|
||||
|
||||
private static List<int> GetPowersportTermList(decimal loanAmount)
|
||||
{
|
||||
var applicableKeys = TermLengths.PowersportByAmount.Keys.Where(x => loanAmount >= x);
|
||||
|
||||
var allowedTerms = new List<int>();
|
||||
|
||||
foreach (var key in applicableKeys)
|
||||
{
|
||||
allowedTerms.AddRange(TermLengths.PowersportByAmount[key]);
|
||||
}
|
||||
|
||||
return allowedTerms;
|
||||
}
|
||||
|
||||
public static bool IsTermRequired(LoanType? loanType)
|
||||
{
|
||||
if (!loanType.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !ValidationConstants.LoansNotRequiringTerm.Contains(loanType.Value);
|
||||
}
|
||||
|
||||
private static bool IsVehicleRequired(LoanType? loanType)
|
||||
{
|
||||
if (!loanType.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ValidationConstants.LoansRequiringVehicle.Contains(loanType.Value);
|
||||
}
|
||||
|
||||
private static bool IsRealEstateRequired(LoanType? loanType)
|
||||
{
|
||||
if (!loanType.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ValidationConstants.LoansRequiringRealEstate.Contains(loanType.Value);
|
||||
}
|
||||
|
||||
private static bool IsHmdaLoan(LoanType? loanType)
|
||||
{
|
||||
if (!loanType.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ValidationConstants.HmdaLoans.Contains(loanType.Value);
|
||||
}
|
||||
|
||||
private static bool IsClientMessageRequired(LoanType? loanType)
|
||||
{
|
||||
if (!loanType.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return loanType.Value == LoanType.S_Special;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user