Skip to content

Commit 13cc339

Browse files
committed
Merge branch 'master' into submission-filename
2 parents 60038bb + 9937968 commit 13cc339

File tree

6 files changed

+100
-10
lines changed

6 files changed

+100
-10
lines changed

publication/src/main/scala/hmda/publication/reports/util/ReportUtil.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ import scala.concurrent.Future
1818
object ReportUtil extends SourceUtils {
1919

2020
def msaReport(fipsCode: String): MSAReport = {
21-
val cbsa = CbsaLookup.values.find(x => x.cbsa == fipsCode).getOrElse(Cbsa())
22-
val stateFips = cbsa.key.substring(0, 2)
23-
val state = StateAbrvLookup.values.find(s => s.state == stateFips).getOrElse(StateAbrv("", "", ""))
24-
MSAReport(fipsCode, CbsaLookup.nameFor(fipsCode), state.stateAbrv, state.stateName)
21+
CbsaLookup.values.find(x => x.cbsa == fipsCode) match {
22+
case Some(cbsa) =>
23+
val stateFips = cbsa.key.substring(0, 2)
24+
val state = StateAbrvLookup.values.find(s => s.state == stateFips).getOrElse(StateAbrv("", "", ""))
25+
MSAReport(fipsCode, CbsaLookup.nameFor(fipsCode), state.stateAbrv, state.stateName)
26+
case None => MSAReport("", "", "", "")
27+
}
2528
}
2629

2730
def calculateMedianIncomeIntervals(fipsCode: Int): Array[Double] = {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package hmda.publication.reports.util
2+
3+
import akka.actor.ActorSystem
4+
import akka.stream.ActorMaterializer
5+
import akka.stream.scaladsl.Source
6+
import hmda.model.fi.lar.LarGenerators
7+
import hmda.model.publication.reports.MSAReport
8+
import hmda.publication.reports.util.ReportUtil._
9+
import hmda.query.repository.filing.LarConverter._
10+
import org.scalatest.{ AsyncWordSpec, MustMatchers }
11+
12+
class ReportUtilSpec extends AsyncWordSpec with MustMatchers with LarGenerators {
13+
14+
implicit val system = ActorSystem()
15+
implicit val ec = system.dispatcher
16+
implicit val materializer = ActorMaterializer()
17+
18+
"msaReport" must {
19+
"get MSA info for given fips code and return MSAReport object" in {
20+
msaReport("10380") mustBe MSAReport("10380", "Aguadilla-Isabela, PR", "PR", "Puerto Rico")
21+
msaReport("26980") mustBe MSAReport("26980", "Iowa City, IA", "IA", "Iowa")
22+
msaReport("41100") mustBe MSAReport("41100", "St. George, UT", "UT", "Utah")
23+
}
24+
25+
"Return empty MSAReport if fips code is invalid" in {
26+
msaReport("bogus") mustBe MSAReport("", "", "", "")
27+
}
28+
}
29+
30+
"calculateMedianIncomeIntervals" must {
31+
"get median income info for given fips, convert to thousands" in {
32+
calculateMedianIncomeIntervals(10380)(2) mustBe 18.267
33+
calculateMedianIncomeIntervals(26980)(2) mustBe 81.027
34+
calculateMedianIncomeIntervals(41100)(2) mustBe 58.145
35+
}
36+
"return array of 50%, 80%, 100%, and 120% levels of median income (in thousands)" in {
37+
def roundTo3(v: Double) = BigDecimal(v).setScale(3, BigDecimal.RoundingMode.HALF_UP).toDouble
38+
calculateMedianIncomeIntervals(26980) mustBe Array(40.5135, 64.8216, 81.027, 97.2324)
39+
calculateMedianIncomeIntervals(41100).map(roundTo3) mustBe Array(29.073, 46.516, 58.145, 69.774)
40+
}
41+
}
42+
43+
"calculateYear" must {
44+
"given a larSource, return the Activity Year for the LARs in it" in {
45+
// Activity Year is the same year as Action Taken Date. This is enforced by edit S270
46+
val lars = larListGen.sample.get.map(_.copy(actionTakenDate = 20090822))
47+
val src = Source.fromIterator(() => lars.toIterator)
48+
.map(lar => toLoanApplicationRegisterQuery(lar))
49+
50+
calculateYear(src).map(_ mustBe 2009)
51+
}
52+
}
53+
54+
}

query/src/main/scala/hmda/query/view/institutions/InstitutionView.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,11 @@ class InstitutionView extends HmdaPersistentActor {
9393
sender() ! state.institutions
9494

9595
case FindInstitutionByPeriodAndDomain(domain) =>
96-
sender() ! state.institutions.filter(i => i.emailDomains.map(e => extractDomain(e)).contains(domain.toLowerCase))
97-
96+
if (domain.isEmpty) {
97+
sender() ! Set.empty[Institution]
98+
} else {
99+
sender() ! state.institutions.filter(i => i.emailDomains.map(e => extractDomain(e)).contains(domain.toLowerCase))
100+
}
98101
}
99102

100103
override def receiveRecover: Receive = super.receiveRecover orElse {

query/src/test/scala/hmda/query/view/institutions/InstitutionViewSpec.scala

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package hmda.query.view.institutions
22

33
import akka.actor.ActorRef
44
import akka.testkit.TestProbe
5-
import hmda.model.institution.InstitutionGenerators
5+
import hmda.model.institution.{ Institution, InstitutionGenerators }
66
import hmda.persistence.messages.CommonMessages.GetState
77
import hmda.persistence.messages.events.institutions.InstitutionEvents.{ InstitutionCreated, InstitutionModified }
88
import hmda.persistence.model.ActorSpec
@@ -17,6 +17,10 @@ class InstitutionViewSpec extends ActorSpec {
1717
val i3 = InstitutionGenerators.sampleInstitution
1818
val i4 = i3.copy(cra = true)
1919

20+
val e1 = Institution.empty.copy(id = "1", emailDomains = Set("test.com", "", ""))
21+
val e2 = Institution.empty.copy(id = "2", emailDomains = Set("", "", ""))
22+
val e3 = Institution.empty.copy(id = "3", emailDomains = Set("test.com", "", ""))
23+
2024
val institutionQuery = createInstitutionView(system)
2125

2226
implicit val ec = system.dispatcher
@@ -29,6 +33,9 @@ class InstitutionViewSpec extends ActorSpec {
2933
institutionQuery ! EventWithSeqNr(2, InstitutionCreated(i2))
3034
institutionQuery ! EventWithSeqNr(3, InstitutionCreated(i3))
3135
institutionQuery ! EventWithSeqNr(4, InstitutionModified(i4))
36+
institutionQuery ! EventWithSeqNr(5, InstitutionCreated(e1))
37+
institutionQuery ! EventWithSeqNr(6, InstitutionCreated(e2))
38+
institutionQuery ! EventWithSeqNr(7, InstitutionCreated(e3))
3239
}
3340

3441
"Institutions View" must {
@@ -50,7 +57,7 @@ class InstitutionViewSpec extends ActorSpec {
5057
}
5158
"return full list of institutions" in {
5259
probe.send(institutionQuery, GetState)
53-
probe.expectMsg(Set(i1, i2, i4))
60+
probe.expectMsg(Set(i1, i2, i4, e1, e2, e3))
5461
}
5562
"return reference to institution query projector" in {
5663
probe.send(institutionQuery, GetProjectionActorRef)
@@ -61,6 +68,21 @@ class InstitutionViewSpec extends ActorSpec {
6168
probe.send(institutionQuery, GetInstitutionByRespondentId(i1.respondentId))
6269
probe.expectMsg(i1)
6370
}
71+
72+
"return a set of institutions that match a domain" in {
73+
probe.send(institutionQuery, FindInstitutionByPeriodAndDomain("test.com"))
74+
probe.expectMsg(Set(e1, e3))
75+
}
76+
77+
"return an empty set when requesting a domain that doesn't exist" in {
78+
probe.send(institutionQuery, FindInstitutionByPeriodAndDomain("notest.com"))
79+
probe.expectMsg(Set())
80+
}
81+
82+
"return an empty set when requesting a blank domain" in {
83+
probe.send(institutionQuery, FindInstitutionByPeriodAndDomain(""))
84+
probe.expectMsg(Set())
85+
}
6486
}
6587

6688
}

validation/src/main/scala/hmda/validation/rules/lar/validity/V280.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ object V280 extends EditCheck[LoanApplicationRegister] {
1111

1212
val cbsaTracts = CBSATractLookup.values
1313

14-
val validMSAs = cbsaTracts.map(cbsa => cbsa.geoIdMsa).toSet
14+
val validMSAs = cbsaTracts.map(cbsa => cbsa.geoIdMsa).filterNot(msa => msa.isEmpty).toSet
1515

16-
val validMDs = cbsaTracts.map(cbsa => cbsa.metDivFp).toSet
16+
val validMDs = cbsaTracts.map(cbsa => cbsa.metDivFp).filterNot(md => md.isEmpty).toSet
1717

1818
override def name: String = "V280"
1919

validation/src/test/scala/hmda/validation/rules/lar/validity/V280Spec.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,13 @@ class V280Spec extends LarEditCheckSpec {
3838
}
3939
}
4040

41+
property("Fails for a blank MSA code") {
42+
forAll(larGen) { lar =>
43+
val inValidGeography = lar.geography.copy(msa = "")
44+
val inValidLar = lar.copy(geography = inValidGeography)
45+
inValidLar.mustFail
46+
}
47+
}
48+
4149
override def check: EditCheck[LoanApplicationRegister] = V280
4250
}

0 commit comments

Comments
 (0)