Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edits 2025 #4893

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft
318 changes: 318 additions & 0 deletions common/src/main/resources/2025EditsDescriptions.txt

Large diffs are not rendered by default.

318 changes: 318 additions & 0 deletions common/src/main/resources/2025QuarterlyEditsDescriptions.txt

Large diffs are not rendered by default.

35 changes: 28 additions & 7 deletions hmda/src/main/scala/hmda/validation/dsl/PredicateHmda.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,33 @@ object PredicateHmda {
}

def exemptionTaken(lar: LoanApplicationRegister): Boolean = {
lar.applicationSubmission == ApplicationSubmissionExempt || lar.ausResult.ausResult1 == AUSResultExempt || lar.ausResult.ausResult2 == AUSResultExempt || lar.ausResult.ausResult3 == AUSResultExempt || lar.ausResult.ausResult4 == AUSResultExempt ||
lar.ausResult.ausResult5 == AUSResultExempt || lar.AUS.aus1 == AUSExempt || lar.AUS.aus2 == AUSExempt || lar.AUS.aus3 == AUSExempt || lar.AUS.aus4 == AUSExempt || lar.AUS.aus5 == AUSExempt ||
lar.nonAmortizingFeatures.balloonPayment == BalloonPaymentExempt || lar.businessOrCommercialPurpose == ExemptBusinessOrCommercialPurpose || lar.applicant.creditScoreType == CreditScoreExempt || lar.coApplicant.creditScoreType == CreditScoreExempt ||
lar.denial.denialReason1 == ExemptDenialReason || lar.denial.denialReason2 == ExemptDenialReason || lar.denial.denialReason3 == ExemptDenialReason || lar.denial.denialReason4 == ExemptDenialReason ||
lar.nonAmortizingFeatures.interestOnlyPayments == InterestOnlyPaymentExempt || lar.lineOfCredit == ExemptLineOfCredit || lar.property.manufacturedHomeLandPropertyInterest == ManufacturedHomeLoanPropertyInterestExempt ||
lar.property.manufacturedHomeSecuredProperty == ManufacturedHomeSecuredExempt || lar.reverseMortgage == ExemptMortgageType || lar.nonAmortizingFeatures.negativeAmortization == NegativeAmortizationExempt || lar.nonAmortizingFeatures.otherNonAmortizingFeatures == OtherNonAmortizingFeaturesExempt ||
lar.payableToInstitution == PayableToInstitutionExempt || lar.loan.interestRate == "Exempt" || lar.geography.zipCode=="Exempt" || lar.geography.city=="Exempt" || lar.geography.street=="Exempt" || lar.geography.state=="Exempt"

lar.applicationSubmission == ApplicationSubmissionExempt ||
lar.ausResult.ausResult1 == AUSResultExempt ||
lar.ausResult.ausResult2 == AUSResultExempt ||
lar.ausResult.ausResult3 == AUSResultExempt ||
lar.ausResult.ausResult4 == AUSResultExempt ||
lar.ausResult.ausResult5 == AUSResultExempt ||
lar.AUS.aus1 == AUSExempt ||
lar.AUS.aus2 == AUSExempt ||
lar.AUS.aus3 == AUSExempt ||
lar.AUS.aus4 == AUSExempt ||
lar.AUS.aus5 == AUSExempt ||
lar.nonAmortizingFeatures.balloonPayment == BalloonPaymentExempt ||
lar.businessOrCommercialPurpose == ExemptBusinessOrCommercialPurpose ||
lar.applicant.creditScoreType == CreditScoreExempt ||
lar.coApplicant.creditScoreType == CreditScoreExempt ||
lar.denial.denialReason1 == ExemptDenialReason ||
lar.denial.denialReason2 == ExemptDenialReason ||
lar.denial.denialReason3 == ExemptDenialReason ||
lar.denial.denialReason4 == ExemptDenialReason ||
lar.nonAmortizingFeatures.interestOnlyPayments == InterestOnlyPaymentExempt ||
lar.lineOfCredit == ExemptLineOfCredit ||
lar.property.manufacturedHomeLandPropertyInterest == ManufacturedHomeLoanPropertyInterestExempt ||
lar.property.manufacturedHomeSecuredProperty == ManufacturedHomeSecuredExempt ||
lar.reverseMortgage == ExemptMortgageType ||
lar.nonAmortizingFeatures.negativeAmortization == NegativeAmortizationExempt ||
lar.nonAmortizingFeatures.otherNonAmortizingFeatures == OtherNonAmortizingFeaturesExempt ||
lar.payableToInstitution == PayableToInstitutionExempt
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package hmda.validation.rules.lar.quality._2025

import hmda.model.filing.lar.LoanApplicationRegister
import hmda.validation.dsl.ValidationResult
import hmda.validation.rules.EditCheck
import hmda.validation.dsl.PredicateHmda._
import hmda.validation.dsl.PredicateCommon._
import hmda.validation.dsl.PredicateSyntax._

import scala.util.Try


object Q616_3 extends EditCheck[LoanApplicationRegister] {
override def name: String = "Q616-3"

override def parent: String = "Q616"

override def apply(lar: LoanApplicationRegister): ValidationResult = {
val discountPoints = BigDecimal(Try(lar.loanDisclosure.discountPoints.toDouble).getOrElse(0.0))
PatrickGoRaft marked this conversation as resolved.
Show resolved Hide resolved
val fifteenPercentLoanAmount = (lar.loan.amount * 0.15).setScale(2, BigDecimal.RoundingMode.HALF_UP)

discountPoints is lessThan(fifteenPercentLoanAmount)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package hmda.validation.rules.lar.quality._2025

import hmda.model.filing.lar.LoanApplicationRegister
import hmda.validation.dsl.PredicateCommon._
import hmda.validation.dsl.PredicateHmda._
import hmda.validation.dsl.PredicateSyntax._
import hmda.validation.dsl.{ValidationFailure, ValidationResult, ValidationSuccess}
import hmda.validation.rules.EditCheck


object Q621 extends EditCheck[LoanApplicationRegister] {
override def name: String = "Q621"

override def parent: String = "Q621"
// valid number between 4 and 12 digits
val regex1 = "^\\d{4,12}$"
PatrickGoRaft marked this conversation as resolved.
Show resolved Hide resolved

override def apply(lar: LoanApplicationRegister): ValidationResult = {
if (lar.larIdentifier.NMLSRIdentifier.matches(regex1) ) {
ValidationSuccess
} else
{
ValidationFailure
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package hmda.validation.rules.lar.quality._2025

import hmda.model.filing.lar.LoanApplicationRegister
import hmda.validation.dsl.PredicateCommon._
import hmda.validation.dsl.PredicateSyntax._
import hmda.validation.dsl.{ValidationFailure, ValidationResult}
import hmda.validation.rules.EditCheck

import scala.util.Try


object Q651_1 extends EditCheck[LoanApplicationRegister] {
override def name: String = "Q651-1"

override def parent: String = "Q651"

override def apply(lar: LoanApplicationRegister): ValidationResult ={
when((lar.loan.combinedLoanToValueRatio is numeric) and
(lar.loan.combinedLoanToValueRatio.toFloat is lessThan(1.5) ) and
PatrickGoRaft marked this conversation as resolved.
Show resolved Hide resolved
(lar.loan.combinedLoanToValueRatio.toFloat is greaterThan(0))) {
ValidationFailure
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package hmda.validation.rules.lar.quality._2025

import hmda.model.filing.lar.LoanApplicationRegister
import hmda.validation.dsl.PredicateCommon._
import hmda.validation.dsl.PredicateSyntax._
import hmda.validation.dsl.ValidationResult
import hmda.validation.rules.EditCheck

import scala.util.Try


object Q651_2 extends EditCheck[LoanApplicationRegister] {
override def name: String = "Q651-2"

override def parent: String = "Q651"

override def apply(lar: LoanApplicationRegister): ValidationResult ={
when(lar.loan.combinedLoanToValueRatio is numeric) {
lar.loan.combinedLoanToValueRatio.toFloat is lessThan(150)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ object Q616_1 extends EditCheck[LoanApplicationRegister] {
override def parent: String = "Q616"

override def apply(lar: LoanApplicationRegister): ValidationResult = {
val dP =
val discountPoints =
Try(lar.loanDisclosure.discountPoints.toDouble).getOrElse(0.0)
val tlc = Try(lar.loanDisclosure.totalLoanCosts.toDouble).getOrElse(0.0)
val totalLoanCosts = Try(lar.loanDisclosure.totalLoanCosts.toDouble).getOrElse(0.0)

when(
lar.loanDisclosure.discountPoints not oneOf("NA", "Exempt") and
(lar.loanDisclosure.totalLoanCosts not oneOf("NA", "Exempt"))
and (dP not equalTo(0.0)) and (tlc not equalTo(0.0))
and (discountPoints not equalTo(0.0)) and (totalLoanCosts not equalTo(0.0))
) {
tlc is greaterThan(dP)
totalLoanCosts is greaterThan(discountPoints)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ object Q616_2 extends EditCheck[LoanApplicationRegister] {
override def parent: String = "Q616"

override def apply(lar: LoanApplicationRegister): ValidationResult = {
val dP =
val discountPoints =
Try(lar.loanDisclosure.discountPoints.toDouble).getOrElse(0.0)
val tpf =
val totalPointsAndFees =
Try(lar.loanDisclosure.totalPointsAndFees.toDouble).getOrElse(0.0)
when(
lar.loanDisclosure.discountPoints not oneOf("NA", "Exempt") and
(lar.loanDisclosure.totalPointsAndFees not oneOf("NA", "Exempt")) and
(dP not equalTo(0.0)) and (tpf not equalTo(0.0))
(discountPoints not equalTo(0.0)) and (totalPointsAndFees not equalTo(0.0))
) {
tpf is greaterThan(dP)
totalPointsAndFees is greaterThan(discountPoints)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package hmda.validation.rules.lar.validity._2025

import hmda.model.filing.lar.LoanApplicationRegister
import hmda.validation.dsl.PredicateCommon._
import hmda.validation.dsl.PredicateSyntax._
import hmda.validation.dsl.ValidationResult
import hmda.validation.rules.EditCheck

object V695_1 extends EditCheck[LoanApplicationRegister] {
override def name: String = "V695-1"

override def parent: String = "V695"

override def apply(lar: LoanApplicationRegister): ValidationResult = {
lar.larIdentifier.NMLSRIdentifier not empty and( (lar.larIdentifier.NMLSRIdentifier is integer) or
(lar.larIdentifier.NMLSRIdentifier is oneOf("Exempt", "NA")))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package hmda.validation.rules.lar.validity._2025

import hmda.model.filing.lar.LoanApplicationRegister
import hmda.validation.dsl.PredicateCommon._
import hmda.validation.dsl.PredicateSyntax._
import hmda.validation.dsl.ValidationResult
import hmda.validation.rules.EditCheck

object V695_2 extends EditCheck[LoanApplicationRegister] {
override def name: String = "V695-2"

override def parent: String = "V695"

override def apply(lar: LoanApplicationRegister): ValidationResult = {
lar.larIdentifier.NMLSRIdentifier not equalTo("0")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package hmda.validation.rules.lar.validity._2025

import hmda.model.filing.lar.LoanApplicationRegister
import hmda.validation.dsl.PredicateCommon._
import hmda.validation.dsl.PredicateSyntax._
import hmda.validation.dsl.{ValidationFailure, ValidationResult, ValidationSuccess}
import hmda.validation.rules.EditCheck

object V695_3 extends EditCheck[LoanApplicationRegister] {
override def name: String = "V695-3"

override def parent: String = "V695"

// valid number between 4 and 12 digits
val regex1 = "^\\d{4,12}$"

override def apply(lar: LoanApplicationRegister): ValidationResult = {
PatrickGoRaft marked this conversation as resolved.
Show resolved Hide resolved
if (lar.larIdentifier.NMLSRIdentifier.matches(regex1) ) {
ValidationSuccess
} else
{
ValidationFailure
}
}

}
Loading