mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 15:56:57 +00:00
Merge branch 'replace_mongodb' into tesobe-rdbms
This commit is contained in:
commit
ed9061ebaa
@ -32,6 +32,13 @@ Berlin 13359, Germany
|
||||
package bootstrap.liftweb
|
||||
|
||||
import code.api.sandbox.SandboxApiCalls
|
||||
import code.metadata.comments.MappedComment
|
||||
import code.metadata.counterparties.{MappedCounterpartyWhereTag, MappedCounterpartyMetadata}
|
||||
import code.metadata.narrative.MappedNarrative
|
||||
import code.metadata.tags.MappedTag
|
||||
import code.metadata.transactionimages.MappedTransactionImage
|
||||
import code.metadata.wheretags.MappedWhereTag
|
||||
import code.metrics.MappedMetric
|
||||
import code.bankbranches.{MappedBankBranch, MappedDataLicense}
|
||||
import code.customerinfo.{MappedCustomerMessage, MappedCustomerInfo}
|
||||
import code.tesobe.{ImporterAPI, CashAccountAPI}
|
||||
@ -48,8 +55,8 @@ import net.liftweb.util.Helpers
|
||||
import java.io.FileInputStream
|
||||
import java.io.File
|
||||
import javax.mail.internet.MimeMessage
|
||||
import code.model.{Nonce, Consumer, Token, dataAccess}
|
||||
import dataAccess._
|
||||
import code.model._
|
||||
import code.model.dataAccess._
|
||||
import code.api._
|
||||
import code.snippet.{OAuthAuthorisation, OAuthWorkedThanks}
|
||||
|
||||
@ -326,6 +333,9 @@ class Boot extends Loggable{
|
||||
object ToSchemify {
|
||||
val models = List(OBPUser, Admin, Nonce, Token, Consumer,
|
||||
ViewPrivileges, ViewImpl, APIUser, MappedAccountHolder,
|
||||
MappedCustomerInfo, MappedCustomerMessage,
|
||||
MappedComment, MappedNarrative, MappedTag,
|
||||
MappedTransactionImage, MappedWhereTag, MappedCounterpartyMetadata,
|
||||
MappedCounterpartyWhereTag, MappedBank, MappedBankAccount, MappedTransaction,
|
||||
MappedMetric, MappedCustomerInfo, MappedCustomerMessage,
|
||||
MappedBankBranch, MappedDataLicense)
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ object Connector extends SimpleInjector {
|
||||
|
||||
val connector = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: Connector = LocalConnector
|
||||
def buildOne: Connector = LocalMappedConnector
|
||||
|
||||
}
|
||||
|
||||
|
||||
190
src/main/scala/code/bankconnectors/LocalMappedConnector.scala
Normal file
190
src/main/scala/code/bankconnectors/LocalMappedConnector.scala
Normal file
@ -0,0 +1,190 @@
|
||||
package code.bankconnectors
|
||||
|
||||
import code.metadata.counterparties.Counterparties
|
||||
import code.model._
|
||||
import code.model.dataAccess.{UpdatesRequestSender, MappedBankAccount, MappedAccountHolder, MappedBank}
|
||||
import code.util.Helper
|
||||
import com.tesobe.model.UpdateBankAccount
|
||||
import net.liftweb.common.{Loggable, Full, Box}
|
||||
import net.liftweb.mapper._
|
||||
import net.liftweb.util.Helpers._
|
||||
import net.liftweb.util.Props
|
||||
|
||||
import scala.concurrent.ops._
|
||||
|
||||
object LocalMappedConnector extends Connector {
|
||||
|
||||
type AccountType = MappedBankAccount
|
||||
|
||||
//gets a particular bank handled by this connector
|
||||
override def getBank(bankId: BankId): Box[Bank] =
|
||||
getMappedBank(bankId)
|
||||
|
||||
private def getMappedBank(bankId: BankId): Box[MappedBank] =
|
||||
MappedBank.find(By(MappedBank.permalink, bankId.value))
|
||||
|
||||
//gets banks handled by this connector
|
||||
override def getBanks: List[Bank] =
|
||||
MappedBank.findAll
|
||||
|
||||
override def getTransaction(bankId: BankId, accountID: AccountId, transactionId: TransactionId): Box[Transaction] = {
|
||||
|
||||
updateAccountTransactions(bankId, accountID)
|
||||
|
||||
MappedTransaction.find(
|
||||
By(MappedTransaction.bank, bankId.value),
|
||||
By(MappedTransaction.account, accountID.value),
|
||||
By(MappedTransaction.transactionId, transactionId.value)).flatMap(_.toTransaction)
|
||||
}
|
||||
|
||||
override def getTransactions(bankId: BankId, accountID: AccountId, queryParams: OBPQueryParam*): Box[List[Transaction]] = {
|
||||
val limit = queryParams.collect { case OBPLimit(value) => MaxRows[MappedTransaction](value) }.headOption
|
||||
val offset = queryParams.collect { case OBPOffset(value) => StartAt[MappedTransaction](value) }.headOption
|
||||
val fromDate = queryParams.collect { case OBPFromDate(date) => By_>=(MappedTransaction.tFinishDate, date) }.headOption
|
||||
val toDate = queryParams.collect { case OBPToDate(date) => By_<=(MappedTransaction.tFinishDate, date) }.headOption
|
||||
val ordering = queryParams.collect {
|
||||
//we don't care about the intended sort field and only sort on finish date for now
|
||||
case OBPOrdering(_, direction) =>
|
||||
direction match {
|
||||
case OBPAscending => OrderBy(MappedTransaction.tFinishDate, Ascending)
|
||||
case OBPDescending => OrderBy(MappedTransaction.tFinishDate, Descending)
|
||||
}
|
||||
}
|
||||
|
||||
val optionalParams : Seq[QueryParam[MappedTransaction]] = Seq(limit.toSeq, offset.toSeq, fromDate.toSeq, toDate.toSeq, ordering.toSeq).flatten
|
||||
val mapperParams = Seq(By(MappedTransaction.bank, bankId.value), By(MappedTransaction.account, accountID.value)) ++ optionalParams
|
||||
|
||||
val mappedTransactions = MappedTransaction.findAll(mapperParams: _*)
|
||||
|
||||
updateAccountTransactions(bankId, accountID)
|
||||
|
||||
for (account <- getBankAccount(bankId, accountID))
|
||||
yield mappedTransactions.flatMap(_.toTransaction(account))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* refreshes transactions via hbci if the transaction info is sourced from hbci
|
||||
*
|
||||
* Checks if the last update of the account was made more than one hour ago.
|
||||
* if it is the case we put a message in the message queue to ask for
|
||||
* transactions updates
|
||||
*
|
||||
* It will be used each time we fetch transactions from the DB. But the test
|
||||
* is performed in a different thread.
|
||||
*/
|
||||
private def updateAccountTransactions(bankId : BankId, accountId : AccountId) = {
|
||||
|
||||
for {
|
||||
bank <- getMappedBank(bankId)
|
||||
account <- getBankAccountType(bankId, accountId)
|
||||
} {
|
||||
spawn{
|
||||
val useMessageQueue = Props.getBool("messageQueue.updateBankAccountsTransaction", false)
|
||||
val outDatedTransactions = now after time(account.lastUpdate.get.getTime + hours(1))
|
||||
if(outDatedTransactions && useMessageQueue) {
|
||||
UpdatesRequestSender.sendMsg(UpdateBankAccount(account.accountNumber.get, bank.national_identifier.get))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def getBankAccountType(bankId: BankId, accountId: AccountId): Box[MappedBankAccount] = {
|
||||
MappedBankAccount.find(
|
||||
By(MappedBankAccount.bank, bankId.value),
|
||||
By(MappedBankAccount.theAccountId, accountId.value))
|
||||
}
|
||||
|
||||
//gets the users who are the legal owners/holders of the account
|
||||
override def getAccountHolders(bankId: BankId, accountID: AccountId): Set[User] =
|
||||
MappedAccountHolder.findAll(
|
||||
By(MappedAccountHolder.accountBankPermalink, bankId.value),
|
||||
By(MappedAccountHolder.accountPermalink, accountID.value)).map(accHolder => accHolder.user.obj).flatten.toSet
|
||||
|
||||
|
||||
def getOtherBankAccount(thisAccountBankId : BankId, thisAccountId : AccountId, metadata : OtherBankAccountMetadata) : Box[OtherBankAccount] = {
|
||||
//because we don't have a db backed model for OtherBankAccounts, we need to construct it from an
|
||||
//OtherBankAccountMetadata and a transaction
|
||||
for { //find a transaction with this counterparty
|
||||
t <- MappedTransaction.find(
|
||||
By(MappedTransaction.bank, thisAccountBankId.value),
|
||||
By(MappedTransaction.account, thisAccountId.value),
|
||||
By(MappedTransaction.counterpartyAccountHolder, metadata.getHolder),
|
||||
By(MappedTransaction.counterpartyAccountNumber, metadata.getAccountNumber))
|
||||
} yield {
|
||||
new OtherBankAccount(
|
||||
//counterparty id is defined to be the id of its metadata as we don't actually have an id for the counterparty itself
|
||||
id = metadata.metadataId,
|
||||
label = metadata.getHolder,
|
||||
nationalIdentifier = t.counterpartyNationalId.get,
|
||||
swift_bic = None,
|
||||
iban = t.getCounterpartyIban(),
|
||||
number = metadata.getAccountNumber,
|
||||
bankName = t.counterpartyBankName.get,
|
||||
kind = t.counterpartyAccountKind.get,
|
||||
originalPartyBankId = thisAccountBankId,
|
||||
originalPartyAccountId = thisAccountId,
|
||||
alreadyFoundMetadata = Some(metadata)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override def getOtherBankAccounts(bankId: BankId, accountID: AccountId): List[OtherBankAccount] =
|
||||
Counterparties.counterparties.vend.getMetadatas(bankId, accountID).flatMap(getOtherBankAccount(bankId, accountID, _))
|
||||
|
||||
override def getOtherBankAccount(bankId: BankId, accountID: AccountId, otherAccountID: String): Box[OtherBankAccount] =
|
||||
Counterparties.counterparties.vend.getMetadata(bankId, accountID, otherAccountID).flatMap(getOtherBankAccount(bankId, accountID, _))
|
||||
|
||||
override def getPhysicalCards(user: User): Set[PhysicalCard] =
|
||||
Set.empty
|
||||
|
||||
override def getPhysicalCardsForBank(bankId: BankId, user: User): Set[PhysicalCard] =
|
||||
Set.empty
|
||||
|
||||
|
||||
override def makePaymentImpl(fromAccount: MappedBankAccount, toAccount: MappedBankAccount, amt: BigDecimal): Box[TransactionId] = {
|
||||
val fromTransAmt = -amt //from account balance should decrease
|
||||
val toTransAmt = amt //to account balance should increase
|
||||
|
||||
//we need to save a copy of this payment as a transaction in each of the accounts involved, with opposite amounts
|
||||
val sentTransactionId = saveTransaction(fromAccount, toAccount, fromTransAmt)
|
||||
saveTransaction(toAccount, fromAccount, toTransAmt)
|
||||
|
||||
sentTransactionId
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a transaction with amount @amt and counterparty @counterparty for account @account. Returns the id
|
||||
* of the saved transaction.
|
||||
*/
|
||||
private def saveTransaction(account : MappedBankAccount, counterparty : BankAccount, amt : BigDecimal) : Box[TransactionId] = {
|
||||
|
||||
val transactionTime = now
|
||||
val currency = account.currency
|
||||
|
||||
|
||||
//update the balance of the account for which a transaction is being created
|
||||
val newAccountBalance : Long = account.accountBalance.get + Helper.convertToSmallestCurrencyUnits(amt, account.currency)
|
||||
account.accountBalance(newAccountBalance).save()
|
||||
|
||||
|
||||
val mappedTransaction = MappedTransaction.create
|
||||
.bank(account.bankId.value)
|
||||
.account(account.accountId.value)
|
||||
.transactionType("sandbox-payment")
|
||||
.amount(Helper.convertToSmallestCurrencyUnits(amt, currency))
|
||||
.newAccountBalance(newAccountBalance)
|
||||
.currency(currency)
|
||||
.tStartDate(transactionTime)
|
||||
.tFinishDate(transactionTime)
|
||||
.description("")
|
||||
.counterpartyAccountHolder(counterparty.accountHolder)
|
||||
.counterpartyAccountNumber(counterparty.number)
|
||||
.counterpartyAccountKind(counterparty.accountType)
|
||||
.counterpartyBankName(counterparty.bankName)
|
||||
.counterpartyIban(counterparty.iban.getOrElse(""))
|
||||
.counterpartyNationalId(counterparty.nationalIdentifier).saveMe
|
||||
|
||||
Full(mappedTransaction.theTransactionId)
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ object Comments extends SimpleInjector {
|
||||
|
||||
val comments = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: Comments = MongoTransactionComments
|
||||
def buildOne: Comments = MappedComments
|
||||
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ trait Comments {
|
||||
|
||||
def getComments(bankId : BankId, accountId : AccountId, transactionId : TransactionId)(viewId : ViewId) : List[Comment]
|
||||
def addComment(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(userId: UserId, viewId : ViewId, text : String, datePosted : Date) : Box[Comment]
|
||||
//TODO: should commentId be unique among all comments, removing the need for the other parameters?
|
||||
def deleteComment(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(commentId : String) : Box[Unit]
|
||||
|
||||
}
|
||||
80
src/main/scala/code/metadata/comments/MappedComment.scala
Normal file
80
src/main/scala/code/metadata/comments/MappedComment.scala
Normal file
@ -0,0 +1,80 @@
|
||||
package code.metadata.comments
|
||||
|
||||
import java.util.{UUID, Date}
|
||||
|
||||
import code.model._
|
||||
import code.model.dataAccess.APIUser
|
||||
import code.util.MappedUUID
|
||||
import net.liftweb.common.{Failure, Full, Box}
|
||||
import net.liftweb.mapper._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
private object MappedComments extends Comments {
|
||||
override def getComments(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(viewId: ViewId): List[Comment] = {
|
||||
MappedComment.findAll(
|
||||
By(MappedComment.bank, bankId.value),
|
||||
By(MappedComment.account, accountId.value),
|
||||
By(MappedComment.transaction, transactionId.value),
|
||||
By(MappedComment.view, viewId.value))
|
||||
}
|
||||
|
||||
override def deleteComment(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(commentId: String): Box[Unit] = {
|
||||
val deleted = for {
|
||||
comment <- MappedComment.find(By(MappedComment.bank, bankId.value),
|
||||
By(MappedComment.account, accountId.value),
|
||||
By(MappedComment.transaction, transactionId.value),
|
||||
By(MappedComment.apiId, commentId))
|
||||
} yield comment.delete_!
|
||||
|
||||
deleted match {
|
||||
case Full(true) => Full(Unit)
|
||||
case _ => Failure("Could not delete comment")
|
||||
}
|
||||
}
|
||||
|
||||
override def addComment(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(userId: UserId, viewId: ViewId, text: String, datePosted: Date): Box[Comment] = {
|
||||
tryo {
|
||||
MappedComment.create
|
||||
.bank(bankId.value)
|
||||
.account(accountId.value)
|
||||
.transaction(transactionId.value)
|
||||
.poster(userId.value)
|
||||
.view(viewId.value)
|
||||
.text_(text)
|
||||
.date(datePosted).saveMe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MappedComment extends Comment with LongKeyedMapper[MappedComment] with IdPK with CreatedUpdated {
|
||||
|
||||
def getSingleton = MappedComment
|
||||
|
||||
object apiId extends MappedUUID(this)
|
||||
|
||||
object text_ extends MappedText(this) {
|
||||
override def defaultValue = ""
|
||||
}
|
||||
object poster extends MappedLongForeignKey(this, APIUser)
|
||||
object replyTo extends MappedUUID(this) {
|
||||
override def defaultValue = ""
|
||||
}
|
||||
|
||||
object view extends MappedString(this, 255)
|
||||
object date extends MappedDateTime(this)
|
||||
|
||||
object bank extends MappedString(this, 255)
|
||||
object account extends MappedString(this, 255)
|
||||
object transaction extends MappedString(this, 255)
|
||||
|
||||
override def id_ : String = apiId.get
|
||||
override def text: String = text_.get
|
||||
override def postedBy: Box[User] = poster.obj
|
||||
override def replyToID: String = replyTo.get
|
||||
override def viewId: ViewId = ViewId(view.get)
|
||||
override def datePosted: Date = date.get
|
||||
}
|
||||
|
||||
object MappedComment extends MappedComment with LongKeyedMetaMapper[MappedComment] {
|
||||
override def dbIndexes = UniqueIndex(apiId) :: Index(view, bank, account, transaction) :: super.dbIndexes
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package code.metadata.counterparties
|
||||
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.util.SimpleInjector
|
||||
import code.model.{AccountId, BankId, OtherBankAccountMetadata, OtherBankAccount}
|
||||
|
||||
@ -7,7 +8,7 @@ object Counterparties extends SimpleInjector {
|
||||
|
||||
val counterparties = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: Counterparties = MongoCounterparties
|
||||
def buildOne: Counterparties = MapperCounterparties
|
||||
|
||||
}
|
||||
|
||||
@ -17,4 +18,6 @@ trait Counterparties {
|
||||
|
||||
//get all counterparty metadatas for a single OBP account
|
||||
def getMetadatas(originalPartyBankId: BankId, originalPartyAccountId : AccountId) : List[OtherBankAccountMetadata]
|
||||
|
||||
def getMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, counterpartyMetadataId : String) : Box[OtherBankAccountMetadata]
|
||||
}
|
||||
@ -0,0 +1,218 @@
|
||||
package code.metadata.counterparties
|
||||
|
||||
import java.util.Date
|
||||
|
||||
import code.model._
|
||||
import code.model.dataAccess.APIUser
|
||||
import code.util.MappedUUID
|
||||
import net.liftweb.common.{Box, Full}
|
||||
import net.liftweb.mapper._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
object MapperCounterparties extends Counterparties {
|
||||
override def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, otherParty: OtherBankAccount): OtherBankAccountMetadata = {
|
||||
|
||||
/**
|
||||
* Generates a new alias name that is guaranteed not to collide with any existing public alias names
|
||||
* for the account in question
|
||||
*/
|
||||
def newPublicAliasName(): String = {
|
||||
import scala.util.Random
|
||||
val firstAliasAttempt = "ALIAS_" + Random.nextLong().toString.take(6)
|
||||
|
||||
/**
|
||||
* Returns true if @publicAlias is already the name of a public alias within @account
|
||||
*/
|
||||
def isDuplicate(publicAlias: String) : Boolean = {
|
||||
MappedCounterpartyMetadata.find(
|
||||
By(MappedCounterpartyMetadata.thisAccountBankId, originalPartyBankId.value),
|
||||
By(MappedCounterpartyMetadata.thisAccountId, originalPartyAccountId.value),
|
||||
By(MappedCounterpartyMetadata.publicAlias, publicAlias)
|
||||
).isDefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends things to @publicAlias until it a unique public alias name within @account
|
||||
*/
|
||||
def appendUntilUnique(publicAlias: String): String = {
|
||||
val newAlias = publicAlias + Random.nextLong().toString.take(1)
|
||||
if (isDuplicate(newAlias)) appendUntilUnique(newAlias)
|
||||
else newAlias
|
||||
}
|
||||
|
||||
if (isDuplicate(firstAliasAttempt)) appendUntilUnique(firstAliasAttempt)
|
||||
else firstAliasAttempt
|
||||
}
|
||||
|
||||
|
||||
//can't find by MappedCounterpartyMetadata.counterpartyId = otherParty.id because in this implementation
|
||||
//if the metadata doesn't exist, the id field of ther OtherBankAccount is not known yet, and will be empty
|
||||
def findMappedCounterpartyMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId,
|
||||
otherParty: OtherBankAccount) : Box[MappedCounterpartyMetadata] = {
|
||||
MappedCounterpartyMetadata.find(
|
||||
By(MappedCounterpartyMetadata.thisAccountBankId, originalPartyBankId.value),
|
||||
By(MappedCounterpartyMetadata.thisAccountId, originalPartyAccountId.value),
|
||||
By(MappedCounterpartyMetadata.holder, otherParty.label),
|
||||
By(MappedCounterpartyMetadata.accountNumber, otherParty.number))
|
||||
}
|
||||
|
||||
val existing = findMappedCounterpartyMetadata(originalPartyBankId, originalPartyAccountId, otherParty)
|
||||
|
||||
existing match {
|
||||
case Full(e) => e
|
||||
case _ => MappedCounterpartyMetadata.create
|
||||
.thisAccountBankId(originalPartyBankId.value)
|
||||
.thisAccountId(originalPartyAccountId.value)
|
||||
.holder(otherParty.label)
|
||||
.publicAlias(newPublicAliasName())
|
||||
.accountNumber(otherParty.number).saveMe
|
||||
}
|
||||
}
|
||||
|
||||
//get all counterparty metadatas for a single OBP account
|
||||
override def getMetadatas(originalPartyBankId: BankId, originalPartyAccountId: AccountId): List[OtherBankAccountMetadata] = {
|
||||
MappedCounterpartyMetadata.findAll(
|
||||
By(MappedCounterpartyMetadata.thisAccountBankId, originalPartyBankId.value),
|
||||
By(MappedCounterpartyMetadata.thisAccountId, originalPartyAccountId.value)
|
||||
)
|
||||
}
|
||||
|
||||
override def getMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, counterpartyMetadataId: String): Box[OtherBankAccountMetadata] = {
|
||||
/**
|
||||
* This particular implementation requires the metadata id to be the same as the otherParty (OtherBankAccount) id
|
||||
*/
|
||||
MappedCounterpartyMetadata.find(
|
||||
By(MappedCounterpartyMetadata.thisAccountBankId, originalPartyBankId.value),
|
||||
By(MappedCounterpartyMetadata.thisAccountId, originalPartyAccountId.value),
|
||||
By(MappedCounterpartyMetadata.counterpartyId, counterpartyMetadataId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class MappedCounterpartyMetadata extends OtherBankAccountMetadata with LongKeyedMapper[MappedCounterpartyMetadata] with IdPK with CreatedUpdated {
|
||||
override def getSingleton = MappedCounterpartyMetadata
|
||||
|
||||
object counterpartyId extends MappedUUID(this)
|
||||
|
||||
//these define the obp account to which this counterparty belongs
|
||||
object thisAccountBankId extends MappedString(this, 255)
|
||||
object thisAccountId extends MappedString(this, 255)
|
||||
|
||||
//these define the counterparty
|
||||
object holder extends MappedString(this, 255)
|
||||
object accountNumber extends MappedString(this, 100)
|
||||
|
||||
//this is the counterparty's metadata
|
||||
object publicAlias extends MappedString(this, 100)
|
||||
object privateAlias extends MappedString(this, 100)
|
||||
object moreInfo extends MappedString(this, 100)
|
||||
object url extends MappedString(this, 100)
|
||||
object imageUrl extends MappedString(this, 100)
|
||||
object openCorporatesUrl extends MappedString(this, 100)
|
||||
|
||||
object physicalLocation extends MappedLongForeignKey(this, MappedCounterpartyWhereTag)
|
||||
object corporateLocation extends MappedLongForeignKey(this, MappedCounterpartyWhereTag)
|
||||
|
||||
/**
|
||||
* Evaluates f, and then attempts to save. If no exceptions are thrown and save executes successfully,
|
||||
* true is returned. If an exception is thrown or if the save fails, false is returned.
|
||||
* @param f the expression to evaluate (e.g. imageUrl("http://example.com/foo.png")
|
||||
* @return If saving the model worked after having evaluated f
|
||||
*/
|
||||
private def trySave(f : => Any) : Boolean =
|
||||
tryo{
|
||||
f
|
||||
save()
|
||||
}.getOrElse(false)
|
||||
|
||||
private def setWhere(whereTag : Box[MappedCounterpartyWhereTag])
|
||||
(userId: UserId, datePosted : Date, longitude : Double, latitude : Double) : Box[MappedCounterpartyWhereTag] = {
|
||||
val toUpdate = whereTag match {
|
||||
case Full(c) => c
|
||||
case _ => MappedCounterpartyWhereTag.create
|
||||
}
|
||||
|
||||
tryo{
|
||||
toUpdate
|
||||
.user(userId.value)
|
||||
.date(datePosted)
|
||||
.geoLongitude(longitude)
|
||||
.geoLatitude(latitude)
|
||||
.saveMe
|
||||
}
|
||||
}
|
||||
|
||||
def setCorporateLocation(userId: UserId, datePosted : Date, longitude : Double, latitude : Double) : Boolean = {
|
||||
//save where tag
|
||||
val savedWhere = setWhere(corporateLocation.obj)(userId, datePosted, longitude, latitude)
|
||||
//set where tag for counterparty
|
||||
savedWhere.map(location => trySave{corporateLocation(location)}).getOrElse(false)
|
||||
}
|
||||
|
||||
def setPhysicalLocation(userId: UserId, datePosted : Date, longitude : Double, latitude : Double) : Boolean = {
|
||||
//save where tag
|
||||
val savedWhere = setWhere(physicalLocation.obj)(userId, datePosted, longitude, latitude)
|
||||
//set where tag for counterparty
|
||||
savedWhere.map(location => trySave{physicalLocation(location)}).getOrElse(false)
|
||||
}
|
||||
|
||||
override def metadataId: String = counterpartyId.get
|
||||
override def getAccountNumber: String = accountNumber.get
|
||||
override def getHolder: String = holder.get
|
||||
override def getPublicAlias: String = publicAlias.get
|
||||
override def getCorporateLocation: Option[GeoTag] =
|
||||
corporateLocation.obj
|
||||
override def getOpenCorporatesURL: String = openCorporatesUrl.get
|
||||
override def getMoreInfo: String = moreInfo.get
|
||||
override def getPrivateAlias: String = privateAlias.get
|
||||
override def getImageURL: String = imageUrl.get
|
||||
override def getPhysicalLocation: Option[GeoTag] =
|
||||
physicalLocation.obj
|
||||
override def getUrl: String = url.get
|
||||
|
||||
override val addPhysicalLocation: (UserId, Date, Double, Double) => Boolean = setPhysicalLocation _
|
||||
override val addCorporateLocation: (UserId, Date, Double, Double) => Boolean = setCorporateLocation _
|
||||
override val addPrivateAlias: (String) => Boolean = (x) =>
|
||||
trySave{privateAlias(x)}
|
||||
override val addURL: (String) => Boolean = (x) =>
|
||||
trySave{url(x)}
|
||||
override val addMoreInfo: (String) => Boolean = (x) =>
|
||||
trySave{moreInfo(x)}
|
||||
override val addPublicAlias: (String) => Boolean = (x) =>
|
||||
trySave{publicAlias(x)}
|
||||
override val addOpenCorporatesURL: (String) => Boolean = (x) =>
|
||||
trySave{openCorporatesUrl(x)}
|
||||
override val addImageURL: (String) => Boolean = (x) =>
|
||||
trySave{imageUrl(x)}
|
||||
override val deleteCorporateLocation = () =>
|
||||
corporateLocation.obj.map(_.delete_!).getOrElse(false)
|
||||
override val deletePhysicalLocation = () =>
|
||||
physicalLocation.obj.map(_.delete_!).getOrElse(false)
|
||||
|
||||
}
|
||||
|
||||
object MappedCounterpartyMetadata extends MappedCounterpartyMetadata with LongKeyedMetaMapper[MappedCounterpartyMetadata] {
|
||||
override def dbIndexes =
|
||||
UniqueIndex(counterpartyId) ::
|
||||
Index(thisAccountBankId, thisAccountId, holder, accountNumber) ::
|
||||
super.dbIndexes
|
||||
}
|
||||
|
||||
class MappedCounterpartyWhereTag extends GeoTag with LongKeyedMapper[MappedCounterpartyWhereTag] with IdPK with CreatedUpdated {
|
||||
|
||||
def getSingleton = MappedCounterpartyWhereTag
|
||||
|
||||
object user extends MappedLongForeignKey(this, APIUser)
|
||||
object date extends MappedDateTime(this)
|
||||
|
||||
//TODO: require these to be valid latitude/longitudes
|
||||
object geoLatitude extends MappedDouble(this)
|
||||
object geoLongitude extends MappedDouble(this)
|
||||
|
||||
override def postedBy: Box[User] = user.obj
|
||||
override def datePosted: Date = date.get
|
||||
override def latitude: Double = geoLatitude.get
|
||||
override def longitude: Double = geoLongitude.get
|
||||
}
|
||||
|
||||
object MappedCounterpartyWhereTag extends MappedCounterpartyWhereTag with LongKeyedMetaMapper[MappedCounterpartyWhereTag]
|
||||
@ -1,8 +1,11 @@
|
||||
package code.metadata.counterparties
|
||||
|
||||
import code.model.{AccountId, BankId, OtherBankAccountMetadata, OtherBankAccount}
|
||||
import net.liftweb.common.Loggable
|
||||
import net.liftweb.common.{Box, Loggable}
|
||||
import com.mongodb.QueryBuilder
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
import net.liftweb.common.Full
|
||||
import org.bson.types.ObjectId
|
||||
|
||||
object MongoCounterparties extends Counterparties with Loggable {
|
||||
|
||||
@ -12,21 +15,25 @@ object MongoCounterparties extends Counterparties with Loggable {
|
||||
Metadata.findAll(query)
|
||||
}
|
||||
|
||||
def getMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, counterpartyMetadataId : String) : Box[OtherBankAccountMetadata] = {
|
||||
/**
|
||||
* This particular implementation requires the metadata id to be the same as the otherParty (OtherBankAccount) id
|
||||
*/
|
||||
for {
|
||||
objId <- tryo { new ObjectId(counterpartyMetadataId) }
|
||||
query = QueryBuilder.start("originalPartyBankId").is(originalPartyBankId.value).put("originalPartyAccountId").is(originalPartyAccountId.value).
|
||||
put("_id").is(objId).get()
|
||||
m <- Metadata.find(query)
|
||||
} yield m
|
||||
}
|
||||
|
||||
def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, otherParty : OtherBankAccount) : OtherBankAccountMetadata = {
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
import net.liftweb.common.Full
|
||||
import org.bson.types.ObjectId
|
||||
|
||||
/**
|
||||
* This particular implementation requires the metadata id to be the same as the otherParty (OtherBankAccount) id
|
||||
*/
|
||||
|
||||
val existing = for {
|
||||
objId <- tryo { new ObjectId(otherParty.id) }
|
||||
query = QueryBuilder.start("originalPartyBankId").is(originalPartyBankId.value).put("originalPartyAccountId").is(originalPartyAccountId.value).
|
||||
put("_id").is(objId).get()
|
||||
m <- Metadata.find(query)
|
||||
} yield m
|
||||
val existing = getMetadata(originalPartyBankId, originalPartyAccountId, otherParty.id)
|
||||
|
||||
val metadata = existing match {
|
||||
case Full(m) => m
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package code.metadata.narrative
|
||||
|
||||
import code.model.{TransactionId, AccountId, BankId}
|
||||
import net.liftweb.common.Full
|
||||
import net.liftweb.mapper._
|
||||
|
||||
object MappedNarratives extends Narrative {
|
||||
|
||||
private def getMappedNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId) = {
|
||||
MappedNarrative.find(By(MappedNarrative.bank, bankId.value),
|
||||
By(MappedNarrative.account, accountId.value),
|
||||
By(MappedNarrative.transaction, transactionId.value))
|
||||
}
|
||||
|
||||
override def getNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(): String = {
|
||||
val found = getMappedNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId)
|
||||
|
||||
found.map(_.narrative.get).getOrElse("")
|
||||
}
|
||||
|
||||
override def setNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(narrative: String): Unit = {
|
||||
|
||||
val existing = getMappedNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId)
|
||||
|
||||
if(narrative.isEmpty) {
|
||||
//if the new narrative is empty, we can just delete the existing one
|
||||
existing.foreach(_.delete_!)
|
||||
} else {
|
||||
val mappedNarrative = existing match {
|
||||
case Full(n) => n
|
||||
case _ => MappedNarrative.create
|
||||
.bank(bankId.value)
|
||||
.account(accountId.value)
|
||||
.transaction(transactionId.value)
|
||||
}
|
||||
mappedNarrative.narrative(narrative).save
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MappedNarrative extends LongKeyedMapper[MappedNarrative] with IdPK with CreatedUpdated {
|
||||
def getSingleton = MappedNarrative
|
||||
|
||||
object bank extends MappedString(this, 255)
|
||||
object account extends MappedString(this, 255)
|
||||
object transaction extends MappedString(this, 255)
|
||||
|
||||
object narrative extends MappedText(this)
|
||||
}
|
||||
|
||||
object MappedNarrative extends MappedNarrative with LongKeyedMetaMapper[MappedNarrative] {
|
||||
override def dbIndexes = Index(bank, account, transaction) :: super.dbIndexes
|
||||
}
|
||||
@ -7,7 +7,7 @@ object Narrative extends SimpleInjector {
|
||||
|
||||
val narrative = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: Narrative = MongoTransactionNarrative
|
||||
def buildOne: Narrative = MappedNarratives
|
||||
|
||||
}
|
||||
|
||||
|
||||
66
src/main/scala/code/metadata/tags/MappedTags.scala
Normal file
66
src/main/scala/code/metadata/tags/MappedTags.scala
Normal file
@ -0,0 +1,66 @@
|
||||
package code.metadata.tags
|
||||
|
||||
import java.util.Date
|
||||
|
||||
import code.model._
|
||||
import code.model.dataAccess.APIUser
|
||||
import code.util.MappedUUID
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
import net.liftweb.mapper._
|
||||
|
||||
object MappedTags extends Tags {
|
||||
override def getTags(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(viewId: ViewId): List[TransactionTag] = {
|
||||
MappedTag.findAll(MappedTag.findQuery(bankId, accountId, transactionId, viewId): _*)
|
||||
}
|
||||
|
||||
override def addTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId)
|
||||
(userId: UserId, viewId: ViewId, tagText: String, datePosted: Date): Box[TransactionTag] = {
|
||||
tryo{
|
||||
MappedTag.create
|
||||
.bank(bankId.value)
|
||||
.account(accountId.value)
|
||||
.transaction(transactionId.value)
|
||||
.view(viewId.value)
|
||||
.user(userId.value)
|
||||
.tag(tagText)
|
||||
.date(datePosted).saveMe
|
||||
}
|
||||
}
|
||||
|
||||
override def deleteTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(tagId: String): Box[Unit] = {
|
||||
//tagId is always unique so we actually don't need to use bankId, accountId, or transactionId
|
||||
MappedTag.find(By(MappedTag.tagId, tagId)).map(_.delete_!).map(x => ()) //TODO: this should return something more useful than Box[Unit]
|
||||
}
|
||||
}
|
||||
|
||||
class MappedTag extends TransactionTag with LongKeyedMapper[MappedTag] with IdPK with CreatedUpdated {
|
||||
def getSingleton = MappedTag
|
||||
|
||||
object bank extends MappedString(this, 255)
|
||||
object account extends MappedString(this, 255)
|
||||
object transaction extends MappedString(this, 255)
|
||||
object view extends MappedString(this, 255)
|
||||
|
||||
object tagId extends MappedUUID(this)
|
||||
|
||||
object user extends MappedLongForeignKey(this, APIUser)
|
||||
object tag extends MappedString(this, 255)
|
||||
object date extends MappedDateTime(this)
|
||||
|
||||
override def id_ : String = tagId.get
|
||||
override def postedBy: Box[User] = user.obj
|
||||
override def value: String = tag.get
|
||||
override def viewId: ViewId = ViewId(view.get)
|
||||
override def datePosted: Date = date.get
|
||||
}
|
||||
|
||||
object MappedTag extends MappedTag with LongKeyedMetaMapper[MappedTag] {
|
||||
override def dbIndexes = Index(bank, account, transaction, view) :: UniqueIndex(tagId) :: super.dbIndexes
|
||||
|
||||
def findQuery(bankId: BankId, accountId: AccountId, transactionId: TransactionId, viewId: ViewId) =
|
||||
By(MappedTag.bank, bankId.value) ::
|
||||
By(MappedTag.account, accountId.value) ::
|
||||
By(MappedTag.transaction, transactionId.value) ::
|
||||
By(MappedTag.view, viewId.value) :: Nil
|
||||
}
|
||||
@ -9,7 +9,7 @@ object Tags extends SimpleInjector {
|
||||
|
||||
val tags = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: Tags = MongoTransactionTags
|
||||
def buildOne: Tags = MappedTags
|
||||
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ trait Tags {
|
||||
|
||||
def getTags(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(viewId : ViewId) : List[TransactionTag]
|
||||
def addTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(userId: UserId, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag]
|
||||
//TODO: viewId? should tagId always be unique -> in that case bankId, accountId, and transactionId would not be required
|
||||
def deleteTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(tagId : String) : Box[Unit]
|
||||
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package code.metadata.transactionimages
|
||||
|
||||
import java.net.URL
|
||||
import java.util.Date
|
||||
import code.model._
|
||||
import code.model.dataAccess.APIUser
|
||||
import code.util.MappedUUID
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.mapper._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
object MapperTransactionImages extends TransactionImages {
|
||||
override def getImagesForTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(viewId: ViewId): List[TransactionImage] = {
|
||||
MappedTransactionImage.findAll(
|
||||
By(MappedTransactionImage.bank, bankId.value),
|
||||
By(MappedTransactionImage.account, accountId.value),
|
||||
By(MappedTransactionImage.transaction, transactionId.value),
|
||||
By(MappedTransactionImage.view, viewId.value)
|
||||
)
|
||||
}
|
||||
|
||||
override def deleteTransactionImage(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(imageId: String): Box[Unit] = {
|
||||
//imageId is unique, so we don't need bankId, accountId, and transactionId
|
||||
//TODO: this should return something more useful than Box[Unit]
|
||||
MappedTransactionImage.find(By(MappedTransactionImage.imageId, imageId)).map(_.delete_!).map(x => ())
|
||||
|
||||
}
|
||||
|
||||
override def addTransactionImage(bankId: BankId, accountId: AccountId, transactionId: TransactionId)
|
||||
(userId: UserId, viewId: ViewId, description: String, datePosted: Date, imageURL: URL): Box[TransactionImage] = {
|
||||
tryo {
|
||||
MappedTransactionImage.create
|
||||
.bank(bankId.value)
|
||||
.account(accountId.value)
|
||||
.transaction(transactionId.value)
|
||||
.view(viewId.value)
|
||||
.user(userId.value)
|
||||
.imageDescription(description)
|
||||
.url(imageURL.toString)
|
||||
.date(datePosted).saveMe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MappedTransactionImage extends TransactionImage with LongKeyedMapper[MappedTransactionImage] with IdPK with CreatedUpdated {
|
||||
def getSingleton = MappedTransactionImage
|
||||
|
||||
object bank extends MappedString(this, 255)
|
||||
object account extends MappedString(this, 255)
|
||||
object transaction extends MappedString(this, 255)
|
||||
object view extends MappedString(this, 255)
|
||||
|
||||
object imageId extends MappedUUID(this)
|
||||
object user extends MappedLongForeignKey(this, APIUser)
|
||||
object date extends MappedDateTime(this)
|
||||
|
||||
object url extends MappedText(this)
|
||||
object imageDescription extends MappedText(this)
|
||||
|
||||
override def id_ : String = imageId.get
|
||||
override def postedBy: Box[User] = user.obj
|
||||
override def description: String = imageDescription.get
|
||||
override def imageUrl: URL = tryo {new URL(url.get)} getOrElse MappedTransactionImage.notFoundUrl
|
||||
override def viewId: ViewId = ViewId(view.get)
|
||||
override def datePosted: Date = date.get
|
||||
}
|
||||
|
||||
object MappedTransactionImage extends MappedTransactionImage with LongKeyedMetaMapper[MappedTransactionImage] {
|
||||
override def dbIndexes = Index(bank, account, transaction, view) :: UniqueIndex(imageId) :: super.dbIndexes
|
||||
|
||||
|
||||
val notFoundUrl = new URL("http://example.com/notfound.png") //TODO: Make this image exist?
|
||||
}
|
||||
@ -10,7 +10,7 @@ object TransactionImages extends SimpleInjector {
|
||||
|
||||
val transactionImages = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: TransactionImages = MongoTransactionImages
|
||||
def buildOne: TransactionImages = MapperTransactionImages
|
||||
|
||||
}
|
||||
|
||||
|
||||
79
src/main/scala/code/metadata/wheretags/MapperWhereTags.scala
Normal file
79
src/main/scala/code/metadata/wheretags/MapperWhereTags.scala
Normal file
@ -0,0 +1,79 @@
|
||||
package code.metadata.wheretags
|
||||
|
||||
import java.util.Date
|
||||
|
||||
import code.model._
|
||||
import code.model.dataAccess.APIUser
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.mapper._
|
||||
|
||||
object MapperWhereTags extends WhereTags {
|
||||
|
||||
private def findMappedWhereTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId, viewId : ViewId) = {
|
||||
MappedWhereTag.find(
|
||||
By(MappedWhereTag.bank, bankId.value),
|
||||
By(MappedWhereTag.account, accountId.value),
|
||||
By(MappedWhereTag.transaction, transactionId.value),
|
||||
By(MappedWhereTag.view, viewId.value))
|
||||
}
|
||||
|
||||
override def addWhereTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId)
|
||||
(userId: UserId, viewId: ViewId, datePosted: Date, longitude: Double, latitude: Double): Boolean = {
|
||||
|
||||
val found = findMappedWhereTag(bankId, accountId, transactionId, viewId)
|
||||
|
||||
val toUpdate = found.getOrElse {
|
||||
MappedWhereTag.create
|
||||
.bank(bankId.value)
|
||||
.account(accountId.value)
|
||||
.transaction(transactionId.value)
|
||||
.view(viewId.value)
|
||||
}
|
||||
|
||||
toUpdate
|
||||
.user(userId.value)
|
||||
.date(datePosted)
|
||||
.geoLatitude(latitude)
|
||||
.geoLongitude(longitude)
|
||||
|
||||
|
||||
tryo{toUpdate.saveMe}.isDefined
|
||||
}
|
||||
|
||||
override def deleteWhereTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(viewId: ViewId): Boolean = {
|
||||
val found = findMappedWhereTag(bankId, accountId, transactionId, viewId)
|
||||
|
||||
found.map(_.delete_!).getOrElse(false)
|
||||
}
|
||||
|
||||
override def getWhereTagForTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(viewId: ViewId): Option[GeoTag] = {
|
||||
findMappedWhereTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId, viewId: ViewId)
|
||||
}
|
||||
}
|
||||
|
||||
class MappedWhereTag extends GeoTag with LongKeyedMapper[MappedWhereTag] with IdPK with CreatedUpdated {
|
||||
|
||||
def getSingleton = MappedWhereTag
|
||||
|
||||
object bank extends MappedString(this, 255)
|
||||
object account extends MappedString(this, 255)
|
||||
object transaction extends MappedString(this, 255)
|
||||
object view extends MappedString(this, 255)
|
||||
|
||||
object user extends MappedLongForeignKey(this, APIUser)
|
||||
object date extends MappedDateTime(this)
|
||||
|
||||
//TODO: require these to be valid latitude/longitudes
|
||||
object geoLatitude extends MappedDouble(this)
|
||||
object geoLongitude extends MappedDouble(this)
|
||||
|
||||
override def datePosted: Date = date.get
|
||||
override def postedBy: Box[User] = user.obj
|
||||
override def latitude: Double = geoLatitude.get
|
||||
override def longitude: Double = geoLongitude.get
|
||||
}
|
||||
|
||||
object MappedWhereTag extends MappedWhereTag with LongKeyedMetaMapper[MappedWhereTag] {
|
||||
override def dbIndexes = Index(bank, account, transaction, view) :: super.dbIndexes
|
||||
}
|
||||
@ -8,7 +8,7 @@ object WhereTags extends SimpleInjector {
|
||||
|
||||
val whereTags = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: WhereTags = MongoTransactionWhereTags
|
||||
def buildOne: WhereTags = MapperWhereTags
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ object APIMetrics extends SimpleInjector {
|
||||
|
||||
val apiMetrics = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: APIMetrics = MongoAPIMetric
|
||||
def buildOne: APIMetrics = MappedMetrics
|
||||
|
||||
/**
|
||||
* Returns a Date which is at the start of the day of the date
|
||||
|
||||
39
src/main/scala/code/metrics/MappedMetrics.scala
Normal file
39
src/main/scala/code/metrics/MappedMetrics.scala
Normal file
@ -0,0 +1,39 @@
|
||||
package code.metrics
|
||||
|
||||
import java.util.Date
|
||||
|
||||
import net.liftweb.mapper._
|
||||
|
||||
object MappedMetrics extends APIMetrics {
|
||||
|
||||
override def saveMetric(url: String, date: Date): Unit = {
|
||||
MappedMetric.create.url(url).date(date).save
|
||||
}
|
||||
|
||||
override def getAllGroupedByDay(): Map[Date, List[APIMetric]] = {
|
||||
//TODO: do this all at the db level using an actual group by query
|
||||
MappedMetric.findAll.groupBy(APIMetrics.getMetricDay)
|
||||
}
|
||||
|
||||
override def getAllGroupedByUrl(): Map[String, List[APIMetric]] = {
|
||||
//TODO: do this all at the db level using an actual group by query
|
||||
MappedMetric.findAll.groupBy(_.getUrl())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MappedMetric extends APIMetric with LongKeyedMapper[MappedMetric] with IdPK {
|
||||
override def getSingleton = MappedMetric
|
||||
|
||||
object url extends MappedText(this)
|
||||
object date extends MappedDateTime(this)
|
||||
|
||||
|
||||
override def getUrl(): String = url.get
|
||||
override def getDate(): Date = date.get
|
||||
|
||||
}
|
||||
|
||||
object MappedMetric extends MappedMetric with LongKeyedMetaMapper[MappedMetric] {
|
||||
override def dbIndexes = Index(url) :: Index(date) :: super.dbIndexes
|
||||
}
|
||||
@ -164,7 +164,9 @@ class AccountOwner(
|
||||
|
||||
case class BankAccountUID(bankId : BankId, accountId : AccountId)
|
||||
|
||||
trait BankAccount extends Loggable {
|
||||
trait BankAccount {
|
||||
|
||||
@transient protected val log = Logger(this.getClass)
|
||||
|
||||
@deprecated
|
||||
def uuid : String
|
||||
@ -192,7 +194,6 @@ trait BankAccount extends Loggable {
|
||||
|
||||
final def owners: Set[User] = {
|
||||
val accountHolders = Connector.connector.vend.getAccountHolders(bankId, accountId)
|
||||
|
||||
if(accountHolders.isEmpty) {
|
||||
//account holders are not all set up in the db yet, so we might not get any back.
|
||||
//In this case, we just use the previous behaviour, which did not return very much information at all
|
||||
@ -215,7 +216,7 @@ trait BankAccount extends Loggable {
|
||||
user match {
|
||||
case Full(u) => u.permittedViews(this)
|
||||
case _ =>{
|
||||
logger.info("no user was found in the permittedViews")
|
||||
log.info("no user was found in the permittedViews")
|
||||
publicViews
|
||||
}
|
||||
}
|
||||
@ -353,7 +354,7 @@ trait BankAccount extends Loggable {
|
||||
val view = Views.views.vend.createView(this, v)
|
||||
|
||||
if(view.isDefined) {
|
||||
logger.info("user: " + userDoingTheCreate.idGivenByProvider + " at provider " + userDoingTheCreate.provider + " created view: " + view.get +
|
||||
log.info("user: " + userDoingTheCreate.idGivenByProvider + " at provider " + userDoingTheCreate.provider + " created view: " + view.get +
|
||||
" for account " + accountId + "at bank " + bankId)
|
||||
}
|
||||
|
||||
@ -368,7 +369,7 @@ trait BankAccount extends Loggable {
|
||||
val view = Views.views.vend.updateView(this, viewId, v)
|
||||
|
||||
if(view.isDefined) {
|
||||
logger.info("user: " + userDoingTheUpdate.idGivenByProvider + " at provider " + userDoingTheUpdate.provider + " updated view: " + view.get +
|
||||
log.info("user: " + userDoingTheUpdate.idGivenByProvider + " at provider " + userDoingTheUpdate.provider + " updated view: " + view.get +
|
||||
" for account " + accountId + "at bank " + bankId)
|
||||
}
|
||||
|
||||
@ -383,7 +384,7 @@ trait BankAccount extends Loggable {
|
||||
val deleted = Views.views.vend.removeView(viewId, this)
|
||||
|
||||
if(deleted.isDefined) {
|
||||
logger.info("user: " + userDoingTheRemove.idGivenByProvider + " at provider " + userDoingTheRemove.provider + " deleted view: " + viewId +
|
||||
log.info("user: " + userDoingTheRemove.idGivenByProvider + " at provider " + userDoingTheRemove.provider + " deleted view: " + viewId +
|
||||
" for account " + accountId + "at bank " + bankId)
|
||||
}
|
||||
|
||||
@ -442,7 +443,6 @@ trait BankAccount extends Loggable {
|
||||
else
|
||||
viewNotAllowed(view)
|
||||
|
||||
|
||||
@deprecated(Helper.deprecatedJsonGenerationMessage)
|
||||
final def overviewJson(user: Box[User]): JObject = {
|
||||
val views = permittedViews(user)
|
||||
|
||||
128
src/main/scala/code/model/MappedTransaction.scala
Normal file
128
src/main/scala/code/model/MappedTransaction.scala
Normal file
@ -0,0 +1,128 @@
|
||||
package code.model
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
import code.bankconnectors.Connector
|
||||
import code.metadata.counterparties.Counterparties
|
||||
import code.util.{Helper, MappedUUID}
|
||||
import net.liftweb.common.{Logger, Box}
|
||||
import net.liftweb.mapper._
|
||||
|
||||
class MappedTransaction extends LongKeyedMapper[MappedTransaction] with IdPK with CreatedUpdated with TransactionUUID {
|
||||
|
||||
private val logger = Logger(classOf[MappedTransaction])
|
||||
|
||||
def getSingleton = MappedTransaction
|
||||
|
||||
object bank extends MappedString(this, 255)
|
||||
object account extends MappedString(this, 255)
|
||||
object transactionId extends MappedString(this, 255) {
|
||||
override def defaultValue = UUID.randomUUID().toString
|
||||
}
|
||||
//TODO: review the need for this
|
||||
object transactionUUID extends MappedUUID(this)
|
||||
object transactionType extends MappedString(this, 20)
|
||||
|
||||
//amount/new balance use the smallest unit of currency! e.g. cents, yen, pence, øre, etc.
|
||||
object amount extends MappedLong(this)
|
||||
object newAccountBalance extends MappedLong(this)
|
||||
|
||||
object currency extends MappedString(this, 10)
|
||||
|
||||
object tStartDate extends MappedDateTime(this)
|
||||
object tFinishDate extends MappedDateTime(this)
|
||||
|
||||
object description extends MappedText(this)
|
||||
|
||||
object counterpartyAccountNumber extends MappedString(this, 60)
|
||||
object counterpartyAccountHolder extends MappedString(this, 100)
|
||||
//still unclear exactly how what this is defined to mean
|
||||
object counterpartyNationalId extends MappedString(this, 40)
|
||||
//this should eventually be calculated using counterpartyNationalId
|
||||
object counterpartyBankName extends MappedString(this, 100)
|
||||
//this should eventually either generate counterpartyAccountNumber or be generated
|
||||
object counterpartyIban extends MappedString(this, 100)
|
||||
object counterpartyAccountKind extends MappedString(this, 40)
|
||||
|
||||
|
||||
override def theTransactionId = TransactionId(transactionId.get)
|
||||
override def theAccountId = AccountId(account.get)
|
||||
override def theBankId = BankId(bank.get)
|
||||
|
||||
def getCounterpartyIban() = {
|
||||
val i = counterpartyIban.get
|
||||
if(i.isEmpty) None else Some(i)
|
||||
}
|
||||
|
||||
def toTransaction(account: BankAccount): Option[Transaction] = {
|
||||
val tBankId = theBankId
|
||||
val tAccId = theAccountId
|
||||
|
||||
if (tBankId != account.bankId || tAccId != account.accountId) {
|
||||
logger.warn("Attempted to convert MappedTransaction to Transaction using unrelated existing BankAccount object")
|
||||
None
|
||||
} else {
|
||||
val label = {
|
||||
val d = description.get
|
||||
if (d.isEmpty) None else Some(d)
|
||||
}
|
||||
|
||||
val transactionCurrency = currency.get
|
||||
val amt = Helper.smallestCurrencyUnitToBigDecimal(amount.get, transactionCurrency)
|
||||
val newBalance = Helper.smallestCurrencyUnitToBigDecimal(newAccountBalance.get, transactionCurrency)
|
||||
|
||||
def createOtherBankAccount(alreadyFoundMetadata : Option[OtherBankAccountMetadata]) = {
|
||||
new OtherBankAccount(
|
||||
id = alreadyFoundMetadata.map(_.metadataId).getOrElse(""),
|
||||
label = counterpartyAccountHolder.get,
|
||||
nationalIdentifier = counterpartyNationalId.get,
|
||||
swift_bic = None, //TODO: need to add this to the json/model
|
||||
iban = getCounterpartyIban(),
|
||||
number = counterpartyAccountNumber.get,
|
||||
bankName = counterpartyBankName.get,
|
||||
kind = counterpartyAccountKind.get,
|
||||
originalPartyBankId = theBankId,
|
||||
originalPartyAccountId = theAccountId,
|
||||
alreadyFoundMetadata = alreadyFoundMetadata
|
||||
)
|
||||
}
|
||||
|
||||
//it's a bit confusing what's going on here, as normally metadata should be automatically generated if
|
||||
//it doesn't exist when an OtherBankAccount object is created. The issue here is that for legacy reasons
|
||||
//otherAccount ids are metadata ids, so the metadata needs to exist before we created the OtherBankAccount
|
||||
//so that we know what id to give it.
|
||||
|
||||
//creates a dummy OtherBankAccount without an OtherBankAccountMetadata, which results in one being generated (in OtherBankAccount init)
|
||||
val dummyOtherBankAccount = createOtherBankAccount(None)
|
||||
|
||||
//and create the proper OtherBankAccount with the correct "id" attribute set to the metadataId of the OtherBankAccountMetadata object
|
||||
//note: as we are passing in the OtherBankAccountMetadata we don't incur another db call to get it in OtherBankAccount init
|
||||
val otherAccount = createOtherBankAccount(Some(dummyOtherBankAccount.metadata))
|
||||
|
||||
Some(new Transaction(
|
||||
transactionUUID.get,
|
||||
theTransactionId,
|
||||
account,
|
||||
otherAccount,
|
||||
transactionType.get,
|
||||
amt,
|
||||
transactionCurrency,
|
||||
label,
|
||||
tStartDate.get,
|
||||
tFinishDate.get,
|
||||
newBalance))
|
||||
}
|
||||
}
|
||||
|
||||
def toTransaction : Option[Transaction] = {
|
||||
for {
|
||||
acc <- Connector.connector.vend.getBankAccount(theBankId, theAccountId)
|
||||
transaction <- toTransaction(acc)
|
||||
} yield transaction
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object MappedTransaction extends MappedTransaction with LongKeyedMetaMapper[MappedTransaction] {
|
||||
override def dbIndexes = UniqueIndex(transactionId, bank, account) :: Index(bank, account) :: super.dbIndexes
|
||||
}
|
||||
29
src/main/scala/code/model/dataAccess/MappedBank.scala
Normal file
29
src/main/scala/code/model/dataAccess/MappedBank.scala
Normal file
@ -0,0 +1,29 @@
|
||||
package code.model.dataAccess
|
||||
|
||||
import code.model.{BankId, Bank}
|
||||
import net.liftweb.mapper._
|
||||
|
||||
class MappedBank extends Bank with LongKeyedMapper[MappedBank] with IdPK with CreatedUpdated {
|
||||
def getSingleton = MappedBank
|
||||
|
||||
object permalink extends MappedString(this, 255)
|
||||
object fullBankName extends MappedString(this, 255)
|
||||
object shortBankName extends MappedString(this, 100)
|
||||
object logoURL extends MappedString(this, 255)
|
||||
object websiteURL extends MappedString(this, 255)
|
||||
object national_identifier extends MappedString(this, 255)
|
||||
|
||||
override def bankId: BankId = BankId(permalink.get)
|
||||
override def fullName: String = fullBankName.get
|
||||
override def shortName: String = shortBankName.get
|
||||
override def logoUrl: String = logoURL.get
|
||||
override def websiteUrl: String = websiteURL.get
|
||||
override def nationalIdentifier: String = national_identifier.get
|
||||
}
|
||||
|
||||
object MappedBank extends MappedBank with LongKeyedMetaMapper[MappedBank] {
|
||||
override def dbIndexes = Index(permalink) :: super.dbIndexes
|
||||
|
||||
def findByBankId(bankId : BankId) =
|
||||
MappedBank.find(By(MappedBank.permalink, bankId.value))
|
||||
}
|
||||
54
src/main/scala/code/model/dataAccess/MappedBankAccount.scala
Normal file
54
src/main/scala/code/model/dataAccess/MappedBankAccount.scala
Normal file
@ -0,0 +1,54 @@
|
||||
package code.model.dataAccess
|
||||
|
||||
import java.math.MathContext
|
||||
|
||||
import code.model._
|
||||
import code.util.Helper
|
||||
import net.liftweb.mapper._
|
||||
|
||||
class MappedBankAccount extends BankAccount with LongKeyedMapper[MappedBankAccount] with IdPK with CreatedUpdated {
|
||||
|
||||
override def getSingleton = MappedBankAccount
|
||||
|
||||
object bank extends MappedString(this, 255)
|
||||
object theAccountId extends MappedString(this, 255)
|
||||
object accountIban extends MappedString(this, 50)
|
||||
object accountCurrency extends MappedString(this, 10)
|
||||
object accountSwiftBic extends MappedString(this, 50)
|
||||
object accountNumber extends MappedString(this, 50)
|
||||
|
||||
@deprecated
|
||||
object holder extends MappedString(this, 100)
|
||||
|
||||
//this is the smallest unit of currency! e.g. cents, yen, pence, øre, etc.
|
||||
object accountBalance extends MappedLong(this)
|
||||
|
||||
object accountName extends MappedString(this, 255)
|
||||
object kind extends MappedString(this, 40)
|
||||
object accountLabel extends MappedString(this, 255)
|
||||
|
||||
//the last time this account was updated via hbci
|
||||
object lastUpdate extends MappedDateTime(this)
|
||||
|
||||
override def accountId: AccountId = AccountId(theAccountId.get)
|
||||
override def iban: Option[String] = {
|
||||
val i = accountIban.get
|
||||
if(i.isEmpty) None else Some(i)
|
||||
}
|
||||
override def bankId: BankId = BankId(bank.get)
|
||||
override def currency: String = accountCurrency.get
|
||||
override def swift_bic: Option[String] = {
|
||||
val sb = accountSwiftBic.get
|
||||
if(sb.isEmpty) None else Some(sb)
|
||||
}
|
||||
override def number: String = accountNumber.get
|
||||
override def balance: BigDecimal = Helper.smallestCurrencyUnitToBigDecimal(accountBalance.get, currency)
|
||||
override def name: String = accountName.get
|
||||
override def accountType: String = kind.get
|
||||
override def label: String = accountLabel.get
|
||||
override def accountHolder: String = holder.get
|
||||
}
|
||||
|
||||
object MappedBankAccount extends MappedBankAccount with LongKeyedMetaMapper[MappedBankAccount] {
|
||||
override def dbIndexes = UniqueIndex(bank, theAccountId) :: super.dbIndexes
|
||||
}
|
||||
100
src/main/scala/code/sandbox/LocalMappedConnectorDataImport.scala
Normal file
100
src/main/scala/code/sandbox/LocalMappedConnectorDataImport.scala
Normal file
@ -0,0 +1,100 @@
|
||||
package code.sandbox
|
||||
|
||||
import code.metadata.counterparties.{MappedCounterpartyMetadata}
|
||||
import code.model.dataAccess.{MappedBankAccount, MappedBank}
|
||||
import code.model.{MappedTransaction, AccountId, BankId}
|
||||
import code.util.Helper.convertToSmallestCurrencyUnits
|
||||
import net.liftweb.common.{Full, Failure, Box}
|
||||
import net.liftweb.mapper.Mapper
|
||||
import net.liftweb.util.Helpers._
|
||||
|
||||
case class MappedSaveable[T <: Mapper[_]](value : T) extends Saveable[T] {
|
||||
def save() = value.save()
|
||||
}
|
||||
|
||||
object LocalMappedConnectorDataImport extends OBPDataImport with CreateViewImpls with CreateOBPUsers {
|
||||
|
||||
type BankType = MappedBank
|
||||
type AccountType = MappedBankAccount
|
||||
type MetadataType = MappedCounterpartyMetadata
|
||||
type TransactionType = MappedTransaction
|
||||
|
||||
protected def createSaveableBanks(data : List[SandboxBankImport]) : Box[List[Saveable[BankType]]] = {
|
||||
val mappedBanks = data.map(bank => {
|
||||
MappedBank.create
|
||||
.permalink(bank.id)
|
||||
.fullBankName(bank.full_name)
|
||||
.shortBankName(bank.short_name)
|
||||
.logoURL(bank.logo)
|
||||
.websiteURL(bank.website)
|
||||
})
|
||||
|
||||
val validationErrors = mappedBanks.flatMap(_.validate)
|
||||
|
||||
if(validationErrors.nonEmpty) {
|
||||
Failure(s"Errors: ${validationErrors.map(_.msg)}")
|
||||
} else {
|
||||
Full(mappedBanks.map(MappedSaveable(_)))
|
||||
}
|
||||
}
|
||||
|
||||
protected def createSaveableAccount(acc : SandboxAccountImport, banks : List[BankType]) : Box[Saveable[AccountType]] = {
|
||||
|
||||
val mappedAccount = for {
|
||||
balance <- tryo{BigDecimal(acc.balance.amount)} ?~ s"Invalid balance: ${acc.balance.amount}"
|
||||
currency = acc.balance.currency
|
||||
} yield {
|
||||
MappedBankAccount.create
|
||||
.theAccountId(acc.id)
|
||||
.bank(acc.bank)
|
||||
.accountLabel(acc.label)
|
||||
.accountNumber(acc.number)
|
||||
.kind(acc.`type`)
|
||||
.accountIban(acc.IBAN)
|
||||
.accountCurrency(currency)
|
||||
.accountBalance(convertToSmallestCurrencyUnits(balance, currency))
|
||||
}
|
||||
|
||||
val validationErrors = mappedAccount.map(_.validate).getOrElse(Nil)
|
||||
|
||||
if(validationErrors.nonEmpty) {
|
||||
Failure(s"Errors: ${validationErrors.map(_.msg)}")
|
||||
} else {
|
||||
mappedAccount.map(MappedSaveable(_))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override protected def createSaveableTransaction(t : SandboxTransactionImport, createdBanks : List[BankType], createdAccounts : List[AccountType]):
|
||||
Box[Saveable[TransactionType]] = {
|
||||
|
||||
for {
|
||||
createdAcc <- Box(createdAccounts.find(acc => acc.accountId == AccountId(t.this_account.id) && acc.bankId == BankId(t.this_account.bank))) ?~ {
|
||||
logger.warn("Data import failed because a created account was not found for a transaction when it should have been")
|
||||
"Server Error"
|
||||
}
|
||||
currency = createdAcc.currency
|
||||
newBalanceValueAsBigDecimal <- tryo{BigDecimal(t.details.new_balance)} ?~ s"Invalid new balance: ${t.details.new_balance}"
|
||||
tValueAsBigDecimal <- tryo{BigDecimal(t.details.value)} ?~ s"Invalid transaction value: ${t.details.value}"
|
||||
postedDate <- tryo{dateFormat.parse(t.details.posted)} ?~ s"Invalid date format: ${t.details.posted}. Expected pattern $datePattern"
|
||||
completedDate <-tryo{dateFormat.parse(t.details.completed)} ?~ s"Invalid date format: ${t.details.completed}. Expected pattern $datePattern"
|
||||
} yield {
|
||||
val mappedTransaction = MappedTransaction.create
|
||||
.bank(t.this_account.bank)
|
||||
.account(t.this_account.id)
|
||||
.transactionId(t.id)
|
||||
.transactionType(t.details.`type`)
|
||||
.amount(convertToSmallestCurrencyUnits(tValueAsBigDecimal, currency))
|
||||
.newAccountBalance(convertToSmallestCurrencyUnits(newBalanceValueAsBigDecimal, currency))
|
||||
.currency(currency)
|
||||
.tStartDate(postedDate)
|
||||
.tFinishDate(completedDate)
|
||||
.description(t.details.description)
|
||||
.counterpartyAccountHolder(t.counterparty.flatMap(_.name).getOrElse(""))
|
||||
.counterpartyAccountNumber(t.counterparty.flatMap(_.account_number).getOrElse(""))
|
||||
|
||||
MappedSaveable(mappedTransaction)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,7 +15,7 @@ object OBPDataImport extends SimpleInjector {
|
||||
|
||||
val importer = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne : OBPDataImport = LocalConnectorDataImport
|
||||
def buildOne : OBPDataImport = LocalMappedConnectorDataImport
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -58,4 +58,40 @@ object Helper{
|
||||
}
|
||||
|
||||
val deprecatedJsonGenerationMessage = "json generation handled elsewhere as it changes from api version to api version"
|
||||
|
||||
/**
|
||||
* Converts a number representing the smallest unit of a currency into a big decimal formatted according to the rules of
|
||||
* that currency. E.g. JPY: 1000 units (yen) => 1000, EUR: 1000 units (cents) => 10.00
|
||||
*/
|
||||
def smallestCurrencyUnitToBigDecimal(units : Long, currencyCode : String) = {
|
||||
BigDecimal(units, currencyDecimalPlaces(currencyCode))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of decimal places a currency has. E.g. "EUR" -> 2, "JPY" -> 0
|
||||
* @param currencyCode
|
||||
* @return
|
||||
*/
|
||||
def currencyDecimalPlaces(currencyCode : String) = {
|
||||
//this data was sourced from Wikipedia, so it might not all be correct,
|
||||
//and some banking systems may still retain different units (e.g. CZK?)
|
||||
//notable it doesn't cover non-traditional currencies (e.g. cryptocurrencies)
|
||||
currencyCode match {
|
||||
//TODO: handle MRO and MGA, which are non-decimal
|
||||
case "CZK" | "JPY" | "KRW" => 0
|
||||
case "KWD" | "OMR" => 3
|
||||
case _ => 2
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* E.g.
|
||||
* amount: BigDecimal("12.45"), currencyCode : "EUR" => 1245
|
||||
* amount: BigDecimal("9034"), currencyCode : "JPY" => 9034
|
||||
*/
|
||||
def convertToSmallestCurrencyUnits(amount : BigDecimal, currencyCode : String) : Long = {
|
||||
val decimalPlaces = Helper.currencyDecimalPlaces(currencyCode)
|
||||
|
||||
(amount * BigDecimal("10").pow(decimalPlaces)).toLong
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package code.api
|
||||
|
||||
//Set the default connector setup here by extending it
|
||||
trait DefaultConnectorTestSetup extends LocalConnectorTestSetup
|
||||
trait DefaultConnectorTestSetup extends LocalMappedConnectorTestSetup
|
||||
72
src/test/scala/code/api/LocalMappedConnectorTestSetup.scala
Normal file
72
src/test/scala/code/api/LocalMappedConnectorTestSetup.scala
Normal file
@ -0,0 +1,72 @@
|
||||
package code.api
|
||||
|
||||
import java.util.Date
|
||||
import bootstrap.liftweb.ToSchemify
|
||||
import code.model.dataAccess._
|
||||
import code.model._
|
||||
import net.liftweb.mapper.MetaMapper
|
||||
import net.liftweb.util.Helpers._
|
||||
|
||||
import scala.util.Random
|
||||
|
||||
trait LocalMappedConnectorTestSetup extends LocalConnectorTestSetup {
|
||||
|
||||
override protected def createBank(id : String) : Bank = {
|
||||
MappedBank.create
|
||||
.fullBankName(randomString(5))
|
||||
.shortBankName(randomString(5))
|
||||
.permalink(id)
|
||||
.national_identifier(randomString(5)).saveMe
|
||||
}
|
||||
|
||||
override protected def createAccount(bankId: BankId, accountId : AccountId, currency : String) : BankAccount = {
|
||||
MappedBankAccount.create
|
||||
.bank(bankId.value)
|
||||
.theAccountId(accountId.value)
|
||||
.accountCurrency(currency)
|
||||
.accountBalance(10000)
|
||||
.holder(randomString(4))
|
||||
.accountNumber(randomString(4))
|
||||
.accountLabel(randomString(4)).saveMe
|
||||
}
|
||||
|
||||
override protected def createTransaction(account: BankAccount, startDate: Date, finishDate: Date) = {
|
||||
//ugly
|
||||
val mappedBankAccount = account.asInstanceOf[MappedBankAccount]
|
||||
|
||||
val accountBalanceBefore = mappedBankAccount.accountBalance.get
|
||||
val transactionAmount = Random.nextInt(1000).toLong
|
||||
val accountBalanceAfter = accountBalanceBefore + transactionAmount
|
||||
|
||||
mappedBankAccount.accountBalance(accountBalanceAfter).save
|
||||
|
||||
MappedTransaction.create
|
||||
.bank(account.bankId.value)
|
||||
.account(account.accountId.value)
|
||||
.transactionType(randomString(5))
|
||||
.tStartDate(startDate)
|
||||
.tFinishDate(finishDate)
|
||||
.currency(account.currency)
|
||||
.amount(transactionAmount)
|
||||
.newAccountBalance(accountBalanceAfter)
|
||||
.description(randomString(5))
|
||||
.counterpartyAccountHolder(randomString(5))
|
||||
.counterpartyAccountKind(randomString(5))
|
||||
.counterpartyAccountNumber(randomString(5))
|
||||
.counterpartyBankName(randomString(5))
|
||||
.counterpartyIban(randomString(5))
|
||||
.counterpartyNationalId(randomString(5))
|
||||
.saveMe
|
||||
.toTransaction.get
|
||||
}
|
||||
|
||||
override protected def wipeTestData() = {
|
||||
//returns true if the model should not be wiped after each test
|
||||
def exclusion(m : MetaMapper[_]) = {
|
||||
m == Nonce || m == Token || m == Consumer || m == OBPUser || m == APIUser
|
||||
}
|
||||
|
||||
//empty the relational db tables after each test
|
||||
ToSchemify.models.filterNot(exclusion).foreach(_.bulkDelete_!!())
|
||||
}
|
||||
}
|
||||
@ -56,6 +56,7 @@ trait ServerSetupWithTestData extends ServerSetup with DefaultConnectorTestSetup
|
||||
override def beforeEach() = {
|
||||
super.beforeEach()
|
||||
|
||||
implicit val dateFormats = net.liftweb.json.DefaultFormats
|
||||
//create fake data for the tests
|
||||
|
||||
//fake banks
|
||||
|
||||
@ -4,7 +4,6 @@ import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
import code.api.test.ServerSetup
|
||||
import net.liftweb.mongodb._
|
||||
|
||||
class MetricsTest extends ServerSetup with WipeMetrics {
|
||||
|
||||
@ -106,7 +105,6 @@ class MetricsTest extends ServerSetup with WipeMetrics {
|
||||
*/
|
||||
trait WipeMetrics {
|
||||
def wipeAllExistingMetrics() = {
|
||||
//just drops all mongodb databases
|
||||
MongoDB.getDb(DefaultMongoIdentifier).foreach(_.dropDatabase())
|
||||
MappedMetric.bulkDelete_!!()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user