Skip to content

Commit

Permalink
enum for status column and more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
davidangb committed Nov 21, 2024
1 parent 41de3cf commit 00525ec
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import cats.implicits.catsSyntaxOptionId
import org.broadinstitute.dsde.rawls.RawlsException
import org.broadinstitute.dsde.rawls.dataaccess.GoogleApiTypes.GoogleApiType
import org.broadinstitute.dsde.rawls.dataaccess.GoogleOperationNames.GoogleOperationName
import org.broadinstitute.dsde.rawls.dataaccess.slick.BillingAccountChangeStatus.BillingAccountChangeStatus
import org.broadinstitute.dsde.rawls.dataaccess.{GoogleApiTypes, GoogleOperationNames}
import org.broadinstitute.dsde.rawls.model.CreationStatuses.CreationStatus
import org.broadinstitute.dsde.rawls.model._
Expand Down Expand Up @@ -101,10 +102,26 @@ final case class BillingAccountChange(id: Long,
newBillingAccount: Option[RawlsBillingAccountName],
created: Instant,
googleSyncTime: Option[Instant],
status: String,
status: BillingAccountChangeStatus,
outcome: Option[Outcome]
)

object BillingAccountChangeStatus extends Enumeration {
type BillingAccountChangeStatus = Value
val Failed: BillingAccountChangeStatus = Value("failed")
val Ignored: BillingAccountChangeStatus = Value("ignored")
val Outstanding: BillingAccountChangeStatus = Value("outstanding")
val Synchronized: BillingAccountChangeStatus = Value("synchronized")

def apply(value: String): BillingAccountChangeStatus = value match {
case "failed" => Failed
case "ignored" => Ignored
case "outstanding" => Outstanding
case "synchronized" => Synchronized
case _ => throw new NoSuchElementException()
}
}

trait RawlsBillingProjectComponent {
this: DriverComponent =>

Expand Down Expand Up @@ -504,7 +521,7 @@ trait RawlsBillingProjectComponent {
newBillingAccount.map(RawlsBillingAccountName),
created.toInstant,
googleSyncTime.map(_.toInstant),
status,
BillingAccountChangeStatus.apply(status),
outcome
)
}
Expand All @@ -520,7 +537,7 @@ trait RawlsBillingProjectComponent {
billingAccountChange.newBillingAccount.map(_.value),
Timestamp.from(billingAccountChange.created),
billingAccountChange.googleSyncTime.map(Timestamp.from),
billingAccountChange.status,
billingAccountChange.status.toString,
outcome,
message
)
Expand Down Expand Up @@ -593,9 +610,11 @@ trait RawlsBillingProjectComponent {

def ignoreAllOutstanding(billingProjectName: RawlsBillingProjectName): WriteAction[Int] =
query
.filter(c => c.billingProjectName === billingProjectName.value && c.status === "outstanding")
.filter(c =>
c.billingProjectName === billingProjectName.value && c.status === BillingAccountChangeStatus.Outstanding.toString
)
.map(_.status)
.update("ignored")
.update(BillingAccountChangeStatus.Ignored.toString)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package org.broadinstitute.dsde.rawls.dataaccess.slick

import cats.implicits.catsSyntaxOptionId
import org.broadinstitute.dsde.rawls.RawlsTestUtils
import org.broadinstitute.dsde.rawls.model.{RawlsBillingAccountName, RawlsBillingProjectName}
import org.broadinstitute.dsde.rawls.model.{RawlsBillingAccountName, RawlsBillingProjectName, RawlsUserSubjectId}
import org.scalatest.OptionValues

import java.sql.SQLException
import java.time.Instant

class RawlsBillingProjectComponentSpec
extends TestDriverComponentWithFlatSpecAndMatchers
with RawlsTestUtils
with OptionValues {
with OptionValues
with RawSqlQuery {

"RawlsBillingProjectComponent" should "save, load and delete" in withDefaultTestDatabase {
// note that create is called in test data save
Expand Down Expand Up @@ -84,7 +86,7 @@ class RawlsBillingProjectComponentSpec
billingAccountChange.value.previousBillingAccount shouldBe previousBillingAccount
billingAccountChange.value.newBillingAccount shouldBe newBillingAccount
billingAccountChange.value.userId shouldBe userId
billingAccountChange.value.status shouldBe "outstanding"
billingAccountChange.value.status shouldBe BillingAccountChangeStatus.Outstanding
}

it should "create a BillingAccountChange record when the Billing Account is set to None" in withDefaultTestDatabase {
Expand All @@ -100,15 +102,14 @@ class RawlsBillingProjectComponentSpec
billingAccountChange.value.previousBillingAccount shouldBe previousBillingAccount
billingAccountChange.value.newBillingAccount shouldBe empty
billingAccountChange.value.userId shouldBe userId
billingAccountChange.value.status shouldBe "outstanding"
billingAccountChange.value.status shouldBe BillingAccountChangeStatus.Outstanding
}

List(Option(RawlsBillingAccountName("avalue")), None) foreach { newBillingAccount =>
it should s"set previous BillingAccountChange records to status=ignored when creating a subsequent change of value $newBillingAccount" in withDefaultTestDatabase {
import driver.api._

val billingProject = testData.testProject3
val previousBillingAccount = billingProject.billingAccount
val userId = testData.userOwner.userSubjectId

// perform the first update; this inserts a billing account change
Expand All @@ -127,14 +128,14 @@ class RawlsBillingProjectComponentSpec
.map(_.headOption)
)
firstChange shouldBe defined
firstChange.value.status shouldBe "outstanding"
firstChange.value.status shouldBe BillingAccountChangeStatus.Outstanding

// perform the second update; this should set the first update to ignored
runAndWait(rawlsBillingProjectQuery.updateBillingAccount(billingProject.projectName, newBillingAccount, userId))
val billingAccountChange = runAndWait(BillingAccountChanges.getLastChange(billingProject.projectName))

billingAccountChange shouldBe defined
billingAccountChange.value.status shouldBe "outstanding"
billingAccountChange.value.status shouldBe BillingAccountChangeStatus.Outstanding

// re-check the first update; it should now be ignored
val firstChangeAgain: Option[BillingAccountChange] =
Expand All @@ -145,7 +146,7 @@ class RawlsBillingProjectComponentSpec
.map(_.headOption)
)
firstChangeAgain shouldBe defined
firstChangeAgain.value.status shouldBe "ignored"
firstChangeAgain.value.status shouldBe BillingAccountChangeStatus.Ignored
}
}

Expand Down Expand Up @@ -224,11 +225,84 @@ class RawlsBillingProjectComponentSpec
}
}

it should "ignoreAllOutstanding correctly" is pending
it should "set statuses properly in ignoreAllOutstanding" in withDefaultTestDatabase {
import driver.api._

// insert some records
val setupSql = sqlu"""
insert into BILLING_ACCOUNT_CHANGES
(BILLING_PROJECT_NAME, USER_ID, PREVIOUS_BILLING_ACCOUNT, NEW_BILLING_ACCOUNT, STATUS)
values
(${testData.testProject1Name.value}, 'user', 'oldaccount', 'newaccount', 'failed'),
(${testData.testProject1Name.value}, 'user', 'oldaccount', 'newaccount', 'synchronized'),
(${testData.testProject1Name.value}, 'user', 'oldaccount', 'newaccount', 'outstanding'),

(${testData.testProject2Name.value}, 'user', 'oldaccount', 'newaccount', 'synchronized'),
(${testData.testProject2Name.value}, 'user', 'oldaccount', 'newaccount', 'synchronized'),
(${testData.testProject2Name.value}, 'user', 'oldaccount', 'newaccount', 'synchronized'),

(${testData.testProject3Name.value}, 'user', 'oldaccount', 'newaccount', 'ignored'),
(${testData.testProject3Name.value}, 'user', 'oldaccount', 'newaccount', 'outstanding'),
(${testData.testProject3Name.value}, 'user', 'oldaccount', 'newaccount', 'outstanding')
;
"""
runAndWait(setupSql)

// validate initial setup
getStatusCountsForProject(testData.testProject1Name) shouldBe Seq(("failed", 1),
("outstanding", 1),
("synchronized", 1)
)
getStatusCountsForProject(testData.testProject2Name) shouldBe Seq(("synchronized", 3))
getStatusCountsForProject(testData.testProject3Name) shouldBe Seq(("ignored", 1), ("outstanding", 2))

// call ignoreAllOutstanding for testProject1Name and validate
runAndWait(BillingAccountChanges.ignoreAllOutstanding(testData.testProject1Name))
getStatusCountsForProject(testData.testProject1Name) shouldBe Seq(("failed", 1),
("ignored", 1),
("synchronized", 1)
)
getStatusCountsForProject(testData.testProject2Name) shouldBe Seq(("synchronized", 3))
getStatusCountsForProject(testData.testProject3Name) shouldBe Seq(("ignored", 1), ("outstanding", 2))

// call ignoreAllOutstanding for testProject2Name and validate
runAndWait(BillingAccountChanges.ignoreAllOutstanding(testData.testProject2Name))
getStatusCountsForProject(testData.testProject1Name) shouldBe Seq(("failed", 1),
("ignored", 1),
("synchronized", 1)
)
getStatusCountsForProject(testData.testProject2Name) shouldBe Seq(("synchronized", 3))
getStatusCountsForProject(testData.testProject3Name) shouldBe Seq(("ignored", 1), ("outstanding", 2))

// call ignoreAllOutstanding for testProject3Name and validate
runAndWait(BillingAccountChanges.ignoreAllOutstanding(testData.testProject3Name))
getStatusCountsForProject(testData.testProject1Name) shouldBe Seq(("failed", 1),
("ignored", 1),
("synchronized", 1)
)
getStatusCountsForProject(testData.testProject2Name) shouldBe Seq(("synchronized", 3))
getStatusCountsForProject(testData.testProject3Name) shouldBe Seq(("ignored", 3))

}

private def getStatusCountsForProject(projectName: RawlsBillingProjectName): Seq[(String, Int)] = {
import driver.api._
val countSql =
sql"""
select STATUS, count(1)
from BILLING_ACCOUNT_CHANGES
where BILLING_PROJECT_NAME = ${projectName.value}
group by STATUS
order by STATUS
""".as[(String, Int)]
runAndWait(countSql)
}

it should "latestChangeForProject correctly" is pending
it should "setOutcome/setGoogleSyncTime should also set status" is pending
it should "replacement for readABillingProjectChange should be correct" is pending

it should "setOutcome/setGoogleSyncTime should also set status" is pending

"BillingAccountChange" should "be able to load records that need to be sync'd" in withDefaultTestDatabase {
runAndWait {
import driver.api._
Expand Down

0 comments on commit 00525ec

Please sign in to comment.