feature/Remove Record support (mongo DB support) so we can update to Liftweb 3.5.0

This commit is contained in:
Marko Milić 2023-01-03 16:02:25 +01:00
parent 3b53b4689a
commit 7dc98ee938
21 changed files with 1 additions and 2464 deletions

View File

@ -169,16 +169,6 @@
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.liftweb</groupId>
<artifactId>lift-mongodb_${scala.version}</artifactId>
<version>${lift.version}</version>
</dependency>
<dependency>
<groupId>net.liftweb</groupId>
<artifactId>lift-mongodb-record_${scala.version}</artifactId>
<version>${lift.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>

View File

@ -17,7 +17,6 @@
#which data connector to use
#connector=mongodb
#connector=rest
#connector=kafka
#connector=obpjvm

View File

@ -332,12 +332,8 @@ class Boot extends MdcLoggable {
// ensure our relational database's tables are created/fit the schema
val connector = APIUtil.getPropsValue("connector").openOrThrowException("no connector set")
if(connector != "mongodb")
schemifyAll()
schemifyAll()
// This sets up MongoDB config (for the mongodb connector)
if( connector == "mongodb")
MongoConfig.init
val runningMode = Props.mode match {
case Props.RunModes.Production => "Production mode"

View File

@ -79,7 +79,6 @@ object Connector extends SimpleInjector {
val nameToConnector: Map[String, () => Connector] = Map(
"mapped" -> lazyValue(LocalMappedConnector),
"akka_vDec2018" -> lazyValue(AkkaConnector_vDec2018),
"mongodb" -> lazyValue(LocalRecordConnector),
"kafka_vSept2018" -> lazyValue(KafkaMappedConnector_vSept2018),
"kafka_vMay2019" -> lazyValue(KafkaMappedConnector_vMay2019),
"rest_vMar2019" -> lazyValue(RestConnector_vMar2019),

View File

@ -1,540 +0,0 @@
package code.bankconnectors
import java.util.{Date, TimeZone}
import code.api.util.ErrorMessages._
import code.api.util._
import code.management.ImporterAPI.ImporterTransaction
import code.metadata.counterparties.{Counterparties, Metadata, MongoCounterparties}
import code.model._
import code.model.dataAccess._
import code.util.Helper
import code.util.Helper.MdcLoggable
import com.mongodb.QueryBuilder
import com.openbankproject.commons.model._
import com.tesobe.model.UpdateBankAccount
import net.liftweb.common.{Box, Empty, Failure, Full}
import net.liftweb.json.Extraction
import net.liftweb.json.JsonAST.JValue
import net.liftweb.mongodb.BsonDSL._
import net.liftweb.util.Helpers._
import org.bson.types.ObjectId
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.model.enums.AccountRoutingScheme
import scala.collection.immutable.List
import scala.concurrent._
private object LocalRecordConnector extends Connector with MdcLoggable {
implicit override val nameOfConnector = LocalRecordConnector.getClass.getSimpleName
override def getBankLegacy(bankId : BankId, callContext: Option[CallContext]) =
getHostedBank(bankId).map(bank =>(bank, callContext))
//gets banks handled by this connector
override def getBanksLegacy(callContext: Option[CallContext]) =
Full(HostedBank.findAll, callContext)
override def getBankAccountLegacy(bankId : BankId, accountId : AccountId, callContext: Option[CallContext]) : Box[(BankAccount, Option[CallContext])] = {
for{
bank <- getHostedBank(bankId)
account <- bank.getAccount(accountId)
} yield (account,callContext)
}
override def getCounterpartyFromTransaction(bankId: BankId, accountId : AccountId, counterpartyID : String): Box[Counterparty] = {
/**
* In this implementation (for legacy reasons), the "otherAccountID" is actually the mongodb id of the
* "other account metadata" object.
*/
for{
objId <- tryo{ new ObjectId(counterpartyID) }
otherAccountmetadata <- {
//"otherAccountID" is actually the mongodb id of the other account metadata" object.
val query = QueryBuilder.
start("_id").is(objId)
.put("originalPartyBankId").is(bankId.value)
.put("originalPartyAccountId").is(accountId.value).get()
Metadata.find(query)
}
} yield{
val query = QueryBuilder
.start("obp_transaction.other_account.holder").is(otherAccountmetadata.holder.get)
// .put("obp_transaction.other_account.number").is(otherAccountmetadata.accountNumber.get)
.get()
val otherAccountFromTransaction : OBPAccount = OBPEnvelope.find(query) match {
case Full(envelope) => envelope.obp_transaction.get.other_account.get
case _ => {
logger.warn("no other account found")
OBPAccount.createRecord
}
}
createOtherBankAccount(bankId, accountId, otherAccountmetadata, otherAccountFromTransaction)
}
}
override def getCounterpartiesFromTransaction(bankId: BankId, accountId : AccountId) = {
/**
* In this implementation (for legacy reasons), the "otherAccountID" is actually the mongodb id of the
* "other account metadata" object.
*/
Full(Counterparties.counterparties.vend.getMetadatas(bankId, accountId).map(meta => {
//for legacy reasons some of the data about the "other account" are stored only on the transactions
//so we need first to get a transaction that match to have the rest of the data
val query = QueryBuilder
.start("obp_transaction.other_account.holder").is(meta.getCounterpartyName)
// .put("obp_transaction.other_account.number").is(meta.getAccountNumber)
.get()
val otherAccountFromTransaction : OBPAccount = OBPEnvelope.find(query) match {
case Full(envelope) => {
envelope.obp_transaction.get.other_account.get
}
case _ => {
logger.warn(s"envelope not found for other account ${meta.getCounterpartyId}")
OBPAccount.createRecord
}
}
createOtherBankAccount(bankId, accountId, meta, otherAccountFromTransaction)
}))
}
override def getTransactionsLegacy(bankId: BankId, accountId: AccountId, callContext: Option[CallContext], queryParams: List[OBPQueryParam]) = {
logger.debug("getTransactions for " + bankId + "/" + accountId)
val transactions = for{
bank <- getHostedBank(bankId)
account <- bank.getAccount(accountId)
} yield {
updateAccountTransactions(bank, account)
account.envelopes(queryParams).map(createTransaction(_, account))
}
transactions.map( transactions => (transactions, callContext))
}
override def getTransactionLegacy(bankId: BankId, accountId : AccountId, transactionId : TransactionId, callContext: Option[CallContext])= {
for{
bank <- getHostedBank(bankId) ?~! s"Transaction not found: bank $bankId not found"
account <- bank.getAccount(accountId) ?~! s"Transaction not found: account $accountId not found"
envelope <- OBPEnvelope.find(account.transactionsForAccount.put("transactionId").is(transactionId.value).get)
} yield {
updateAccountTransactions(bank, account)
(createTransaction(envelope,account), callContext)
}
}
override protected def makePaymentImpl(fromAccount: BankAccount, toAccount: BankAccount, transactionRequestCommonBody: TransactionRequestCommonBodyJSON, amt: BigDecimal, description: String, transactionRequestType: TransactionRequestType, chargePolicy: String): Box[TransactionId] = {
val fromTransAmt = -amt //from account balance should decrease
val toTransAmt = amt //to account balance should increase
//this is the transaction that gets attached to the account of the person making the payment
val createdFromTrans = saveNewTransaction(fromAccount, fromTransAmt, description)
// this creates the transaction that gets attached to the account of the person receiving the payment
// saveNewTransaction(toAccount, fromAccount, toTransAmt, description)
//assumes OBPEnvelope id is what gets used as the Transaction id in the API. If that gets changed, this needs to
//be updated (the tests should fail if it doesn't)
createdFromTrans.map(t => TransactionId(t.transactionId.get))
}
private def createTransaction(env: OBPEnvelope, theAccount: Account): Transaction = {
val transaction: OBPTransaction = env.obp_transaction.get
val otherAccount_ = transaction.other_account.get
val id = TransactionId(env.transactionId.get)
val uuid = id.value
//slight hack required: otherAccount id is, for legacy reasons, the mongodb id of its metadata object
//so we have to find that
val query = QueryBuilder.start("originalPartyBankId").is(theAccount.bankId.value).
put("originalPartyAccountId").is(theAccount.permalink.get).
put("accountNumber").is(otherAccount_.number.get).
put("holder").is(otherAccount_.holder.get).get
//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 mongo metadata ids, so the metadata needs to exist before we created the OtherBankAccount
//so that we know what id to give it. That's why there's a hardcoded dependency on MongoCounterparties.
val metadata = Metadata.find(query) match {
case Full(m) => m
case _ => MongoCounterparties.createMetadata(
theAccount.bankId,
theAccount.accountId,
otherAccount_.holder.get,
otherAccount_.number.get)
}
val otherAccount = new Counterparty(
counterpartyId = metadata.getCounterpartyId,
counterpartyName = otherAccount_.holder.get,
nationalIdentifier = otherAccount_.bank.get.national_identifier.get,
otherBankRoutingAddress = None,
otherAccountRoutingAddress = Some(otherAccount_.bank.get.IBAN.get),
thisAccountId = AccountId(otherAccount_.number.get),
thisBankId = BankId(otherAccount_.bank.get.name.get),
kind = otherAccount_.kind.get,
otherBankRoutingScheme = "",
otherAccountRoutingScheme="",
otherAccountProvider = "",
isBeneficiary = true
)
val transactionType = transaction.details.get.kind.get
val amount = transaction.details.get.value.get.amount.get
val currency = transaction.details.get.value.get.currency.get
val label = Some(transaction.details.get.label.get)
val startDate = transaction.details.get.posted.get
val finishDate = transaction.details.get.completed.get
val balance = transaction.details.get.new_balance.get.amount.get
new Transaction(
uuid,
id,
theAccount,
otherAccount,
transactionType,
amount,
currency,
label,
startDate,
finishDate,
balance)
}
private def saveNewTransaction(account : BankAccount, amount : BigDecimal, description : String) : Box[OBPEnvelope] = {
val oldBalance = account.balance
def saveAndUpdateAccountBalance(transactionJS : JValue, thisAccount : BankAccount) : Box[OBPEnvelope] = {
val envelope: Box[OBPEnvelope] = OBPEnvelope.envelopesFromJValue(transactionJS)
val account = thisAccount.asInstanceOf[Account]
if(envelope.isDefined) {
val e : OBPEnvelope = envelope.openOrThrowException(attemptedToOpenAnEmptyBox)
logger.debug(s"Updating current balance for ${account.bankName} / ${account.accountNumber} / ${account.accountType}")
account.accountBalance(e.obp_transaction.get.details.get.new_balance.get.amount.get).save(true)
logger.debug("Saving new transaction")
Full(e.save(true))
} else {
Failure("couldn't save transaction")
}
}
for {
// otherBank <- Connector.connector.vend.getBank(otherAccount.bankId) ?~! "no other bank found"
transTime <- Full(now)
//mongodb/the lift mongo thing wants a literal Z in the timestamp, apparently
envJsonDateFormat = {
val simpleDateFormat = APIUtil.DateWithMsFormat
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"))
simpleDateFormat
}
envJson =
"obp_transaction" ->
("this_account" ->
// ("holder" -> account.owners.headOption.map(_.name).getOrElse("")) ~ //TODO: this is rather fragile...
("number" -> account.number) ~
("kind" -> account.accountType) ~
("bank" ->
("IBAN" -> account.accountRoutings.find(_.scheme == AccountRoutingScheme.IBAN.toString).map(_.address).getOrElse("")) ~
("national_identifier" -> account.nationalIdentifier) ~
("name" -> account.bankId.value))) ~
// ("other_account" ->
//// ("holder" -> otherAccount.accountHolder) ~
//// ("number" -> otherAccount.number) ~
//// ("kind" -> otherAccount.accountType) ~
// ("bank" ->
// ("IBAN" -> "") ~
//// ("national_identifier" -> otherBank.nationalIdentifier) ~
//// ("name" -> otherBank.fullName))) ~
("details" ->
("type_en" -> "") ~
("type_de" -> "") ~
("posted" ->
("$dt" -> envJsonDateFormat.format(transTime))
) ~
("completed" ->
("$dt" -> envJsonDateFormat.format(transTime))
) ~
("new_balance" ->
("currency" -> account.currency) ~
("amount" -> (oldBalance + amount).toString)) ~
("value" ->
("currency" -> account.currency) ~
("amount" -> amount.toString)))
saved <- saveAndUpdateAccountBalance(envJson, account)
} yield {
saved
}
}
/**
* 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(bank: HostedBank, account: Account): Unit = {
Future {
val useMessageQueue = APIUtil.getPropsAsBoolValue("messageQueue.updateBankAccountsTransaction", false)
val outDatedTransactions = now after time(account.accountLastUpdate.get.getTime + hours(APIUtil.getPropsAsIntValue("messageQueue.updateTransactionsInterval", 1)))
if(outDatedTransactions && useMessageQueue) {
UpdatesRequestSender.sendMsg(UpdateBankAccount(account.accountNumber.get, bank.national_identifier.get))
}
}
}
private def createOtherBankAccount(originalPartyBankId: BankId, originalPartyAccountId: AccountId,
otherAccount : CounterpartyMetadata, otherAccountFromTransaction : OBPAccount) : Counterparty = {
new Counterparty(
counterpartyId = otherAccount.getCounterpartyId,
counterpartyName = otherAccount.getCounterpartyName,
nationalIdentifier = otherAccountFromTransaction.bank.get.national_identifier.get,
otherBankRoutingAddress = None,
otherAccountRoutingAddress = Some(otherAccountFromTransaction.bank.get.IBAN.get),
thisAccountId = AccountId(otherAccountFromTransaction.number.get),
thisBankId = BankId(otherAccountFromTransaction.bank.get.name.get),
kind = "",
otherBankRoutingScheme = "",
otherAccountRoutingScheme="",
otherAccountProvider = "",
isBeneficiary = true
)
}
private def getHostedBank(bankId : BankId) : Box[HostedBank] = {
HostedBank.find("permalink", bankId.value) ?~ {"bank " + bankId + " not found"}
}
//Need to pass in @hostedBank because the Account model doesn't have any references to BankId, just to the mongo id of the Bank object (which itself does have the bank id)
private def createAccount(hostedBank : HostedBank, accountId : AccountId, accountNumber: String,
accountType: String, accountLabel: String, currency : String, initialBalance : BigDecimal, holderName : String) : BankAccount = {
import net.liftweb.mongodb.BsonDSL._
Account.find(
(Account.accountNumber.name -> accountNumber)~
(Account.bankID.name -> hostedBank.id.get)
) match {
case Full(bankAccount) => {
logger.debug(s"account with number ${bankAccount.accountNumber} at bank ${hostedBank.bankId} already exists. No need to create a new one.")
bankAccount
}
case _ => {
logger.debug("creating account record ")
val bankAccount =
Account
.createRecord
.accountBalance(initialBalance)
.holder(holderName)
.accountNumber(accountNumber)
.kind(accountType)
.accountLabel(accountLabel)
.accountName("")
.permalink(accountId.value)
.bankID(hostedBank.id.get)
.accountCurrency(currency)
.accountIban("")
.accountLastUpdate(now)
.save(true)
bankAccount
}
}
}
//creates a bank account (if it doesn't exist) and creates a bank (if it doesn't exist)
override def createBankAndAccount(
bankName: String,
bankNationalIdentifier: String,
accountNumber: String,
accountType: String,
accountLabel: String,
currency: String,
accountHolderName: String,
branchId: String,
accountRoutingScheme: String,
accountRoutingAddress: String
) = {
// TODO: use a more unique id for the long term
val hostedBank = {
// TODO: use a more unique id for the long term
HostedBank.find(HostedBank.national_identifier.name, bankNationalIdentifier) match {
case Full(b)=> {
logger.debug(s"bank ${b.name} found")
b
}
case _ =>{
//TODO: if name is empty use bank id as name alias
//TODO: need to handle the case where generatePermalink returns a permalink that is already used for another bank
logger.debug(s"creating HostedBank")
HostedBank
.createRecord
.name(bankName)
.alias(bankName)
.permalink(Helper.generatePermalink(bankName))
.national_identifier(bankNationalIdentifier)
.save(true)
}
}
}
val createdAccount = createAccount(hostedBank, AccountId(APIUtil.generateUUID()),
accountNumber, accountType, accountLabel, currency, BigDecimal("0.00"), accountHolderName)
Full((hostedBank, createdAccount))
}
//for sandbox use -> allows us to check if we can generate a new test account with the given number
override def accountExists(bankId: BankId, accountNumber: String) = {
import net.liftweb.mongodb.BsonDSL._
getHostedBank(bankId).map(_.id.get) match {
case Full(mongoId) =>
Full(Account.count((Account.accountNumber.name -> accountNumber) ~ (Account.bankID.name -> mongoId)) > 0)
case _ =>
logger.warn("tried to check account existence for an account at a bank that doesn't exist")
Full(false)
}
}
override def removeAccount(bankId: BankId, accountId: AccountId) = {
import net.liftweb.mongodb.BsonDSL._
for {
account <- Account.find((Account.bankID.name -> bankId.value) ~ (Account.accountId.value -> accountId.value)) ?~
s"No account found with number ${accountId} at bank with id ${bankId}: could not save envelope"
} yield {
account.delete_!
}
Full(false)
/* account
} match {
case Full(acc) => acc.
}
*/
}
//creates a bank account for an existing bank, with the appropriate values set
override def createSandboxBankAccount(
bankId: BankId,
accountId: AccountId,
accountNumber: String,
accountType: String,
accountLabel: String,
currency: String,
initialBalance: BigDecimal,
accountHolderName: String,
branchId: String,
accountRoutings: List[AccountRouting]
): Box[BankAccount] = {
HostedBank.find(bankId) match {
case Full(b) => Full(createAccount(b, accountId, accountNumber, accountType, accountLabel, currency, initialBalance, accountHolderName))
case _ => Failure(s"Bank with id ${bankId.value} not found. Cannot create account at non-existing bank.")
}
}
//used by transaction import api call to check for duplicates
override def getMatchingTransactionCount(bankNationalIdentifier : String, accountNumber : String, amount: String, completed: Date, otherAccountHolder: String) = {
val baseQuery = QueryBuilder.start("obp_transaction.details.value.amount")
.is(amount)
.put("obp_transaction.details.completed")
.is(completed)
.put("obp_transaction.this_account.bank.national_identifier")
.is(bankNationalIdentifier)
.put("obp_transaction.this_account.number")
.is(accountNumber)
//this is refactored legacy code, and it seems the empty account holder check had to do with potentially missing
//fields in the db. not sure if this is still required.
if(otherAccountHolder.isEmpty){
def emptyHolderOrEmptyString(holder: Box[String]): Boolean = {
holder match {
case Full(s) => s.isEmpty
case _ => true
}
}
val partialMatches = OBPEnvelope.findAll(baseQuery.get())
Full(partialMatches.filter(e => {
emptyHolderOrEmptyString(e.obp_transaction.get.other_account.get.holder.valueBox)
}).size)
}
else{
val qry = baseQuery.put("obp_transaction.other_account.holder").is(otherAccountHolder).get
val partialMatches = OBPEnvelope.count(qry)
Full(partialMatches.toInt)//icky
}
}
//used by transaction import api
override def createImportedTransaction(transaction: ImporterTransaction): Box[Transaction] = {
import net.liftweb.mongodb.BsonDSL._
implicit val formats = CustomJsonFormats.losslessFormats
val asJValue = Extraction.decompose(transaction)
for {
env <- OBPEnvelope.envelopesFromJValue(asJValue)
nationalIdentifier = transaction.obp_transaction.this_account.bank.national_identifier
bank <- HostedBank.find(HostedBank.national_identifier.name -> nationalIdentifier) ?~
s"No bank found with national identifier ${nationalIdentifier} could not save envelope"
accountNumber = transaction.obp_transaction.this_account.number
account <- Account.find((Account.bankID.name -> bank.id.get) ~ (Account.accountNumber.name -> accountNumber)) ?~
s"No account found with number ${accountNumber} at bank with id ${bank.bankId}: could not save envelope"
savedEnv <- env.saveTheRecord() ?~ "Could not save envelope"
} yield {
createTransaction(savedEnv, account)
}
}
//used by the transaction import api
override def updateAccountBalance(bankId: BankId, accountId: AccountId, newBalance: BigDecimal) = {
getBankAccountOld(bankId, accountId).map(_.asInstanceOf[Account]) match {
case Full(acc) =>
acc.accountBalance(newBalance).saveTheRecord().isDefined
Full(true)
case _ =>
Full(false)
}
}
override def setBankAccountLastUpdated(bankNationalIdentifier: String, accountNumber : String, updateDate: Date) = {
Account.find(
(Account.accountNumber.name -> accountNumber)~
(Account.nationalIdentifier -> bankNationalIdentifier)
) match {
case Full(acc) => Full(acc.accountLastUpdate(updateDate).saveTheRecord().isDefined)
case _ => logger.warn("can't set bank account.lastUpdated because the account was not found"); Full(false)
}
}
override def updateAccountLabel(bankId: BankId, accountId: AccountId, label: String) = {
getBankAccountOld(bankId, accountId).map(_.asInstanceOf[Account]) match {
case Full(acc) =>
acc.accountLabel(label).saveTheRecord().isDefined
Full(true)
case _ =>
Full(false)
}
}
}

View File

@ -1,81 +0,0 @@
package code.metadata.comments
import code.model._
import java.util.Date
import code.util.Helper.MdcLoggable
import net.liftweb.common.{Box, Full}
import org.bson.types.ObjectId
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model._
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk}
import net.liftweb.record.field.{LongField, StringField}
private object MongoTransactionComments extends Comments {
def getComments(bankId : BankId, accountId : AccountId, transactionId : TransactionId)(viewId : ViewId) : List[Comment] = {
OBPComment.findAll(bankId, accountId, transactionId, viewId)
}
def addComment(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(userId: UserPrimaryKey, viewId : ViewId, text : String, datePosted : Date) : Box[Comment] = {
OBPComment.createRecord.userId(userId.value).
transactionId(transactionId.value).
accountId(accountId.value).
bankId(bankId.value).
textField(text).
date(datePosted).
forView(viewId.value).saveTheRecord()
}
def deleteComment(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(commentId : String) : Box[Boolean] = {
//use delete with find query to avoid concurrency issues
OBPComment.delete(OBPComment.getFindQuery(bankId, accountId, transactionId, commentId))
//we don't have any useful information here so just assume it worked
Full(true)
}
def bulkDeleteComments(bankId: BankId, accountId: AccountId): Boolean = ???
def bulkDeleteCommentsOnTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId) : Boolean = ???
}
private class OBPComment private() extends MongoRecord[OBPComment] with ObjectIdPk[OBPComment] with Comment {
def meta = OBPComment
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
def postedBy = UserX.findByResourceUserId(userId.get)
def viewId = ViewId(forView.get)
def text = textField.get
def datePosted = date.get
def id_ = id.get.toString
def replyToID = replyTo.get
object userId extends LongField(this)
object forView extends StringField(this, 255)
object textField extends StringField(this, 255)
object date extends DateField(this)
object replyTo extends StringField(this,255)
}
private object OBPComment extends OBPComment with MongoMetaRecord[OBPComment] with MdcLoggable {
def findAll(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : List[OBPComment] = {
val query = QueryBuilder.
start("bankId").is(bankId.value).
put("accountId").is(accountId.value).
put("transactionId").is(transactionId.value).
put("forView").is(viewId.value).get
findAll(query)
}
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId, commentId : String) : DBObject = {
//in theory commentId should be enough as we're just using the mongoId
QueryBuilder.start("_id").is(new ObjectId(commentId)).put("transactionId").is(transactionId.value).
put("accountId").is(accountId.value).put("bankId").is(bankId.value).get()
}
}

View File

@ -1,182 +0,0 @@
package code.metadata.counterparties
import java.util.Date
import code.api.util.CallContext
import code.model._
import code.util.Helper.MdcLoggable
import com.mongodb.QueryBuilder
import com.openbankproject.commons.model._
import net.liftweb.common.{Box, Empty, Full}
import net.liftweb.util.Helpers.tryo
import org.bson.types.ObjectId
object MongoCounterparties extends Counterparties with MdcLoggable {
def getMetadatas(originalPartyBankId: BankId, originalPartyAccountId : AccountId) : List[CounterpartyMetadata] = {
val query = QueryBuilder.start("originalPartyBankId").is(originalPartyBankId.value).put("originalPartyAccountId").is(originalPartyAccountId.value).get
Metadata.findAll(query)
}
def getMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, counterpartyMetadataId : String) : Box[CounterpartyMetadata] = {
/**
* 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 deleteMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, counterpartyMetadataId: String): Box[Boolean] = Empty
def getOrCreateMetadata(bankId: BankId, accountId : AccountId, counterpartyId:String, counterpartyName:String) : Box[CounterpartyMetadata] = {
/**
* This particular implementation requires the metadata id to be the same as the otherParty (OtherBankAccount) id
*/
val existing = getMetadata(bankId, accountId, counterpartyId)
val metadata = existing match {
case Full(m) => m
case _ => createMetadata(bankId, accountId, counterpartyName, counterpartyId)
}
Full(metadata)
}
/**
* This only exists for OBPEnvelope. Avoid using it for any other reason outside of this class
*/
def createMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, otherAccountHolder : String, counterpartyId : String) : Metadata = {
//create it
if(otherAccountHolder.isEmpty){
logger.info("other account holder is Empty. creating a metadata record with private alias")
//no holder name, nothing to hide, so we don't need to create a public alias
Metadata
.createRecord
.counterpartyId(counterpartyId)
.originalPartyBankId(originalPartyBankId.value)
.originalPartyAccountId(originalPartyAccountId.value)
// .accountNumber(otherAccountNumber)
.holder("")
.save(true)
} else {
Metadata.createRecord.
counterpartyId(counterpartyId).
originalPartyBankId(originalPartyBankId.value).
originalPartyAccountId(originalPartyAccountId.value).
holder(otherAccountHolder).
// accountNumber(otherAccountNumber).
publicAlias(newPublicAliasName(originalPartyBankId, originalPartyAccountId)).save(true)
}
}
/**
* Generates a new alias name that is guaranteed not to collide with any existing public alias names
* for the account in question
*/
def newPublicAliasName(originalPartyBankId : BankId, originalPartyAccountId : AccountId): 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) = {
val query = QueryBuilder.start("originalPartyBankId").is(originalPartyBankId.value).put("originalPartyAccountId").is(originalPartyAccountId.value).get()
Metadata.findAll(query).exists(m => {
m.publicAlias.get == publicAlias
})
}
/**
* 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
}
override def getCounterparty(counterpartyId : String): Box[CounterpartyTrait] = Empty
override def deleteCounterparty(counterpartyId : String): Box[Boolean] = Empty
override def getCounterpartyByIban(iban : String): Box[CounterpartyTrait] = Empty
override def getCounterpartyByIbanAndBankAccountId(iban : String, bankId: BankId, accountId: AccountId): Box[CounterpartyTrait] = Empty
override def getCounterpartyByRoutings(
otherBankRoutingScheme: String,
otherBankRoutingAddress: String,
otherBranchRoutingScheme: String,
otherBranchRoutingAddress: String,
otherAccountRoutingScheme: String,
otherAccountRoutingAddress: String
): Box[CounterpartyTrait] = Empty
override def getCounterpartyBySecondaryRouting(
otherAccountSecondaryRoutingScheme: String,
otherAccountSecondaryRoutingAddress: String
): Box[CounterpartyTrait] = Empty
override def createCounterparty(
createdByUserId: String,
thisBankId: String,
thisAccountId: String,
thisViewId: String,
name: String,
otherAccountRoutingScheme: String,
otherAccountRoutingAddress: String,
otherBankRoutingScheme: String,
otherBankRoutingAddress: String,
otherBranchRoutingScheme: String,
otherBranchRoutingAddress: String,
isBeneficiary: Boolean,
otherAccountSecondaryRoutingScheme: String,
otherAccountSecondaryRoutingAddress: String,
description: String,
currency: String,
bespoke: List[CounterpartyBespoke]
): Box[CounterpartyTrait] = Empty
override def checkCounterpartyExists(
name: String,
thisBankId: String,
thisAccountId: String,
thisViewId: String
): Box[CounterpartyTrait] = Empty
override def getCounterparties(thisBankId: BankId, thisAccountId: AccountId, viewId: ViewId): Box[List[CounterpartyTrait]] = ???
override def addPublicAlias(counterpartyId : String, alias: String): Box[Boolean] = ???
override def addPrivateAlias(counterpartyId : String, alias: String): Box[Boolean] = ???
override def addURL(counterpartyId : String, url: String): Box[Boolean] = ???
override def addImageURL(counterpartyId : String, imageUrl: String): Box[Boolean] = ???
override def addOpenCorporatesURL(counterpartyId : String, url: String): Box[Boolean] = ???
override def addMoreInfo(counterpartyId : String, moreInfo: String): Box[Boolean] = ???
override def addPhysicalLocation(counterpartyId : String, userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double): Box[Boolean] = ???
override def addCorporateLocation(counterpartyId : String, userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double): Box[Boolean] = ???
override def deletePhysicalLocation(counterpartyId : String): Box[Boolean] = ???
override def deleteCorporateLocation(counterpartyId : String): Box[Boolean] = ???
override def getCorporateLocation(counterpartyId : String): Box[GeoTag] = ???
override def getPhysicalLocation(counterpartyId : String): Box[GeoTag] = ???
override def getOpenCorporatesURL(counterpartyId : String): Box[String] = ???
override def getImageURL(counterpartyId : String): Box[String] = ???
override def getUrl(counterpartyId : String): Box[String] = ???
override def getMoreInfo(counterpartyId : String): Box[String] = ???
override def getPublicAlias(counterpartyId : String): Box[String] = ???
override def getPrivateAlias(counterpartyId : String): Box[String] = ???
override def bulkDeleteAllCounterparties(): Box[Boolean] = ???
}

View File

@ -1,156 +0,0 @@
package code.metadata.counterparties
import code.model.UserX
import net.liftweb.mongodb.record.{BsonMetaRecord, BsonRecord, MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.ObjectIdPk
import net.liftweb.record.field.StringField
import com.openbankproject.commons.model.{CounterpartyMetadata, GeoTag, UserPrimaryKey}
//TODO: this should be private
class Metadata private() extends CounterpartyMetadata with MongoRecord[Metadata] with ObjectIdPk[Metadata] {
import net.liftweb.mongodb.record.field.BsonRecordField
import java.util.Date
def meta = Metadata
//originalPartyBankId and originalPartyAccountId are used to identify the account
//which has the counterparty this metadata is associated with
object originalPartyBankId extends StringField(this, 100)
object originalPartyAccountId extends StringField(this, 100)
object counterpartyId extends StringField(this,100)
object holder extends StringField(this, 255)
// object accountNumber extends StringField(this, 100)
object publicAlias extends StringField(this, 100)
object privateAlias extends StringField(this, 100)
object moreInfo extends StringField(this, 100)
object url extends StringField(this, 100)
object imageUrl extends StringField(this, 100)
object openCorporatesUrl extends StringField(this, 100) {
override def optional_? = true
}
object corporateLocation extends BsonRecordField(this, OBPGeoTag)
object physicalLocation extends BsonRecordField(this, OBPGeoTag)
def addCorporateLocationFn(userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double) : Boolean = {
val newTag = OBPGeoTag.createRecord.
userId(userId.value).
date(datePosted).
geoLongitude(longitude).
geoLatitude(latitude)
corporateLocation(newTag).saveTheRecord()
true
}
def deleteCorporateLocationFn : Boolean = {
corporateLocation.clear
this.saveTheRecord()
true
}
def addPhysicalLocationFn(userId: UserPrimaryKey, datePosted : Date, longitude : Double, latitude : Double) : Boolean = {
val newTag = OBPGeoTag.createRecord.
userId(userId.value).
date(datePosted).
geoLongitude(longitude).
geoLatitude(latitude)
physicalLocation(newTag).saveTheRecord()
true
}
def deletePhysicalLocationFn : Boolean = {
physicalLocation.clear
this.saveTheRecord()
true
}
private def locationTag(loc: OBPGeoTag): Option[GeoTag]={
if(loc.longitude==0 && loc.latitude==0)
None
else
Some(loc)
}
override def getCounterpartyId = counterpartyId.get
override def getCounterpartyName = holder.get
// override def getAccountNumber = accountNumber.get
override def getUrl = url.get
override def getCorporateLocation = locationTag(corporateLocation.get)
override def getPhysicalLocation = locationTag(physicalLocation.get)
override val deleteCorporateLocation = deleteCorporateLocationFn _
override val deletePhysicalLocation = deletePhysicalLocationFn _
override def getPrivateAlias = privateAlias.get
override def getPublicAlias = publicAlias.get
override def getMoreInfo = moreInfo.get
override def getImageURL: String = imageUrl.get
override val addPrivateAlias: (String) => Boolean = (alias => {
privateAlias(alias).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override val addURL: (String) => Boolean = (text => {
url(text).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override val addPhysicalLocation: (UserPrimaryKey, Date, Double, Double) => Boolean = addPhysicalLocationFn _
override val addCorporateLocation: (UserPrimaryKey, Date, Double, Double) => Boolean = addCorporateLocationFn _
override val addMoreInfo: (String) => Boolean = (text => {
moreInfo(text).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override def getOpenCorporatesURL: String = openCorporatesUrl.get
override val addPublicAlias: (String) => Boolean = (alias => {
publicAlias(alias).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override val addOpenCorporatesURL: (String) => Boolean = (text => {
openCorporatesUrl(text).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
override val addImageURL: (String) => Boolean = (text => {
imageUrl(text).saveTheRecord()
//the save method does not return a Boolean to inform about the saving state,
//so we a true
true
})
}
//TODO: this should be private
object Metadata extends Metadata with MongoMetaRecord[Metadata]
class OBPGeoTag private() extends BsonRecord[OBPGeoTag] with GeoTag {
import com.openbankproject.commons.model.User
import net.liftweb.record.field.{DoubleField, LongField}
import net.liftweb.mongodb.record.field.DateField
def meta = OBPGeoTag
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object userId extends LongField(this)
object date extends DateField(this)
object geoLongitude extends DoubleField(this,0)
object geoLatitude extends DoubleField(this,0)
override def datePosted = date.get
override def postedBy = UserX.findByResourceUserId(userId.get)
override def longitude = geoLongitude.get
override def latitude = geoLatitude.get
}
//TODO: this should be private
object OBPGeoTag extends OBPGeoTag with BsonMetaRecord[OBPGeoTag]

View File

@ -1,78 +0,0 @@
package code.metadata.narrative
import net.liftweb.common.Full
import net.liftweb.mongodb.BsonDSL._
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.ObjectIdPk
import net.liftweb.record.field.StringField
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model.{AccountId, BankId, TransactionId}
private object MongoTransactionNarrative extends Narrative {
def getNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId)() : String = {
OBPNarrative.find(OBPNarrative.getFindQuery(bankId, accountId, transactionId)) match {
case Full(n) => n.narrative.get
case _ => ""
}
}
def setNarrative(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(narrative: String) : Boolean = {
val findQuery = OBPNarrative.getFindQuery(bankId, accountId, transactionId)
if(narrative.isEmpty) {
//if we're setting the value of the narrative to "" then we can just delete it
//use delete with find query to avoid concurrency issues
OBPNarrative.delete(findQuery)
} else {
//avoiding upsert for now as it seemed to behave a little strangely
val found = OBPNarrative.find(findQuery)
found match {
case Full(f) => f.narrative(narrative).save(true)
case _ => {
OBPNarrative.createRecord
.transactionId(transactionId.value)
.accountId(accountId.value)
.bankId(bankId.value)
.narrative(narrative).save(true)
}
}
}
//we don't have any useful information here so just assume it worked
true
}
override def bulkDeleteNarrativeOnTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId): Boolean = ???
override def bulkDeleteNarratives(bankId: BankId, accountId: AccountId): Boolean = ???
}
private class OBPNarrative private() extends MongoRecord[OBPNarrative] with ObjectIdPk[OBPNarrative] {
def meta = OBPNarrative
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object narrative extends StringField(this, 255)
}
private object OBPNarrative extends OBPNarrative with MongoMetaRecord[OBPNarrative] {
def init = createIndex((transactionId.name -> 1) ~ (accountId.name -> 1) ~ (bankId.name -> 1), true)
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId) : DBObject = {
QueryBuilder.start("bankId").is(bankId.value).put("accountId").is(accountId.value).put("transactionId").is(transactionId.value).get
}
}
object OBPNarrativeInit {
def init = OBPNarrative.init
}

View File

@ -1,96 +0,0 @@
package code.metadata.tags
import code.model._
import java.util.Date
import code.util.Helper
import net.liftweb.common.{Box, Full}
import org.bson.types.ObjectId
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk}
import net.liftweb.record.field.{LongField, StringField}
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model._
private object MongoTransactionTags extends Tags {
def getTags(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(viewId : ViewId) : List[TransactionTag] = {
OBPTag.findAll(bankId, accountId, transactionId, viewId)
}
def getTagsOnAccount(bankId : BankId, accountId : AccountId)(viewId : ViewId) : List[TransactionTag] = {
OBPTag.findAll(bankId, accountId, TransactionId(""), viewId)
}
def addTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag] = {
OBPTag.createRecord.
bankId(bankId.value).
accountId(accountId.value).
transactionId(transactionId.value).
userId(userId.value).
forView(viewId.value).
tag(tagText).
date(datePosted).saveTheRecord()
}
def addTagOnAccount(bankId : BankId, accountId : AccountId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag] = {
OBPTag.createRecord.
bankId(bankId.value).
accountId(accountId.value).
userId(userId.value).
forView(viewId.value).
tag(tagText).
date(datePosted).saveTheRecord()
}
def deleteTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(tagId : String) : Box[Boolean] = {
//use delete with find query to avoid concurrency issues
OBPTag.delete(OBPTag.getFindQuery(bankId, accountId, transactionId, tagId))
//we don't have any useful information here so just assume it worked
Full(true)
}
def deleteTagOnAccount(bankId : BankId, accountId : AccountId)(tagId : String) : Box[Boolean] = {
deleteTag(bankId, accountId, TransactionId(""))(tagId)
}
def bulkDeleteTags(bankId: BankId, accountId: AccountId): Boolean = ???
def bulkDeleteTagsOnTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId) : Boolean = ???
}
private class OBPTag private() extends MongoRecord[OBPTag] with ObjectIdPk[OBPTag] with TransactionTag {
def meta = OBPTag
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object userId extends LongField(this)
object forView extends StringField(this, 255)
object tag extends StringField(this, 255)
object date extends DateField(this)
def id_ = id.get.toString
def datePosted = date.get
def postedBy = UserX.findByResourceUserId(userId.get)
def viewId = ViewId(forView.get)
def value = tag.get
}
private object OBPTag extends OBPTag with MongoMetaRecord[OBPTag] {
def findAll(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : List[OBPTag] = {
val query = QueryBuilder.
start("bankId").is(bankId.value).
put("accountId").is(accountId.value).
put("transactionId").is(transactionId.value).
put("forView").is(viewId.value).get
findAll(query)
}
//in theory commentId should be enough as we're just using the mongoId
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId, tagId : String) : DBObject = {
QueryBuilder.start("_id").is(new ObjectId(tagId)).put("transactionId").is(transactionId.value).
put("accountId").is(accountId.value).put("bankId").is(bankId.value).get()
}
}

View File

@ -1,95 +0,0 @@
package code.metadata.transactionimages
import code.model._
import code.util.Helper
import net.liftweb.common.Box
import code.util.Helper.MdcLoggable
import java.net.URL
import java.util.Date
import org.bson.types.ObjectId
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk}
import net.liftweb.record.field.{LongField, StringField}
import net.liftweb.util.Helpers._
import net.liftweb.common.Full
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model._
private object MongoTransactionImages extends TransactionImages with MdcLoggable {
def getImagesForTransaction(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(viewId : ViewId) : List[TransactionImage] = {
OBPTransactionImage.findAll(bankId, accountId, transactionId, viewId)
}
def addTransactionImage(bankId : BankId, accountId : AccountId, transactionId: TransactionId)
(userId: UserPrimaryKey, viewId : ViewId, description : String, datePosted : Date, imageURL: String) : Box[TransactionImage] = {
OBPTransactionImage.createRecord.
bankId(bankId.value).
accountId(accountId.value).
transactionId(transactionId.value).
userId(userId.value).
forView(viewId.value).
imageComment(description).
date(datePosted).
url(imageURL.toString).saveTheRecord()
}
def deleteTransactionImage(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(imageId : String) : Box[Boolean] = {
//use delete with find query to avoid concurrency issues
OBPTransactionImage.delete(OBPTransactionImage.getFindQuery(bankId, accountId, transactionId, imageId))
//we don't have any useful information here so just assume it worked
Full(true)
}
def bulkDeleteImagesOnTransaction(bankId : BankId, accountId : AccountId, transactionId: TransactionId) : Boolean = ???
def bulkDeleteTransactionImage(bankId: BankId, accountId: AccountId): Boolean = ???
}
private class OBPTransactionImage private() extends MongoRecord[OBPTransactionImage]
with ObjectIdPk[OBPTransactionImage] with TransactionImage {
def meta = OBPTransactionImage
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object userId extends LongField(this)
object forView extends StringField(this, 255)
object imageComment extends StringField(this, 1000)
object date extends DateField(this)
object url extends StringField(this, 500)
def id_ = id.get.toString
def datePosted = date.get
def postedBy = UserX.findByResourceUserId(userId.get)
def viewId = ViewId(forView.get)
def description = imageComment.get
def imageUrl = {
tryo {new URL(url.get)} getOrElse OBPTransactionImage.notFoundUrl
}
}
private object OBPTransactionImage extends OBPTransactionImage with MongoMetaRecord[OBPTransactionImage] {
val notFoundUrl = new URL("http://example.com/notfound.png") //TODO: Make this image exist?
def findAll(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : List[OBPTransactionImage] = {
val query = QueryBuilder.
start("bankId").is(bankId.value).
put("accountId").is(accountId.value).
put("transactionId").is(transactionId.value).
put("forView").is(viewId.value).get
findAll(query)
}
//in theory commentId should be enough as we're just using the mongoId
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId, imageId : String) : DBObject = {
QueryBuilder.start("_id").is(new ObjectId(imageId)).put("transactionId").is(transactionId.value).
put("accountId").is(accountId.value).put("bankId").is(bankId.value).get()
}
}

View File

@ -1,56 +0,0 @@
package code.metadata.wheretags
import java.util.Date
import code.model._
import net.liftweb.common.{Box, Full}
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.model._
private object MongoTransactionWhereTags extends WhereTags with MdcLoggable {
def addWhereTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)
(userId: UserPrimaryKey, viewId : ViewId, datePosted : Date, longitude : Double, latitude : Double) : Boolean = {
//avoiding upsert for now as it seemed to behave a little strangely
val findQuery = OBPWhereTag.getFindQuery(bankId, accountId, transactionId, viewId)
val found = OBPWhereTag.find(findQuery)
found match {
case Full(f) => {
f.date(datePosted).
geoLongitude(longitude).
geoLatitude(latitude).save(true)
}
case _ => {
OBPWhereTag.createRecord.
bankId(bankId.value).
accountId(accountId.value).
transactionId(transactionId.value).
userId(userId.value).
forView(viewId.value).
date(datePosted).
geoLongitude(longitude).
geoLatitude(latitude).save(true)
}
}
//we don't have any useful information here so just return true
true
}
def deleteWhereTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(viewId: ViewId): Boolean = {
//use delete with find query to avoid concurrency issues
OBPWhereTag.delete(OBPWhereTag.getFindQuery(bankId, accountId, transactionId, viewId))
//we don't have any useful information here so just return true
true
}
def getWhereTagForTransaction(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(viewId : ViewId) : Box[GeoTag] = {
OBPWhereTag.find(bankId, accountId, transactionId, viewId)
}
def bulkDeleteWhereTagsOnTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId) : Boolean = ???
def bulkDeleteWhereTags(bankId: BankId, accountId: AccountId) : Boolean = ???
}

View File

@ -1,52 +0,0 @@
package code.metadata.wheretags
import net.liftweb.mongodb.BsonDSL._
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk}
import net.liftweb.record.field.{DoubleField, LongField, StringField}
import code.model._
import com.mongodb.{DBObject, QueryBuilder}
import com.openbankproject.commons.model._
private class OBPWhereTag private() extends MongoRecord[OBPWhereTag] with ObjectIdPk[OBPWhereTag] with GeoTag {
def meta = OBPWhereTag
//These fields are used to link this to its transaction
object transactionId extends StringField(this, 255)
object accountId extends StringField(this, 255)
object bankId extends StringField(this, 255)
object userId extends LongField(this)
object forView extends StringField(this, 255)
object date extends DateField(this)
object geoLongitude extends DoubleField(this,0)
object geoLatitude extends DoubleField(this,0)
override def datePosted = date.get
override def postedBy = UserX.findByResourceUserId(userId.get)
override def longitude = geoLongitude.get
override def latitude = geoLatitude.get
}
private object OBPWhereTag extends OBPWhereTag with MongoMetaRecord[OBPWhereTag] {
def init = createIndex((transactionId.name -> 1) ~ (accountId.name -> 1) ~ (bankId.name -> 1) ~ (forView.name -> 1), true)
def find(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : Option[OBPWhereTag] = {
val query = getFindQuery(bankId, accountId, transactionId, viewId)
find(query)
}
//in theory commentId should be enough as we're just using the mongoId
def getFindQuery(bankId : BankId, accountId : AccountId, transactionId : TransactionId, viewId : ViewId) : DBObject = {
QueryBuilder.start("forView").is(viewId.value).put("transactionId").is(transactionId.value).
put("accountId").is(accountId.value).put("bankId").is(bankId.value).get()
}
}
object OBPWhereTagInit {
def init = OBPWhereTag.init
}

View File

@ -1,122 +0,0 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.metrics
import java.util.Date
import code.api.util.OBPQueryParam
import net.liftweb.common.Box
import net.liftweb.mongodb.record.field.{DateField, LongPk}
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.record.field.{IntField, LongField, StringField}
import scala.concurrent.Future
private class MongoAPIMetric extends MongoRecord[MongoAPIMetric] with LongPk[MongoAPIMetric] with APIMetric {
def meta = MongoAPIMetric
object userId extends StringField(this,255)
object url extends StringField(this,255)
object date extends DateField(this)
object duration extends LongField(this)
object userName extends StringField(this,255)
object appName extends StringField(this,255)
object developerEmail extends StringField(this,255)
//The consumerId, Foreign key to Consumer not key
object consumerId extends StringField(this,255)
//name of the Scala Partial Function being used for the endpoint
object implementedByPartialFunction extends StringField(this,255)
//name of version where the call is implemented) -- S.request.get.view
object implementedInVersion extends StringField(this,255)
//(GET, POST etc.) --S.request.get.requestType
object verb extends StringField(this,255)
object httpCode extends IntField(this)
object correlationId extends StringField(this,255)
def getMetricId(): Long = id.get
def getUrl() = url.get
def getDate() = date.get
def getDuration(): Long = duration.get
def getUserId() = userId.get
def getUserName(): String = userName.get
def getAppName(): String = appName.get
def getDeveloperEmail(): String = developerEmail.get
override def getConsumerId(): String = consumerId.get
override def getImplementedByPartialFunction(): String = implementedByPartialFunction.get
override def getImplementedInVersion(): String = implementedInVersion.get
override def getVerb(): String = verb.get
override def getHttpCode(): Int = httpCode.get
override def getCorrelationId(): String = correlationId.get
}
private object MongoAPIMetric extends MongoAPIMetric with MongoMetaRecord[MongoAPIMetric] with APIMetrics {
def saveMetric(userId: String, url: String, date: Date, duration: Long, userName: String, appName: String, developerEmail: String, consumerId: String, implementedByPartialFunction: String, implementedInVersion: String, verb: String, httpCode: Option[Int], correlationId: String): Unit = {
MongoAPIMetric.createRecord.
userId(userId).
url(url).
date(date).
duration(duration).
userName(userName).
appName(appName).
developerEmail(developerEmail).
consumerId(consumerId).
implementedByPartialFunction(implementedByPartialFunction).
implementedInVersion(implementedInVersion).
verb(verb).
correlationId(correlationId)
saveTheRecord()
}
override def saveMetricsArchive(primaryKey: Long, userId: String, url: String, date: Date, duration: Long, userName: String, appName: String, developerEmail: String, consumerId: String, implementedByPartialFunction: String, implementedInVersion: String, verb: String, httpCode: Option[Int], correlationId: String): Unit = ???
// def getAllGroupedByUrl() : Map[String, List[APIMetric]] = {
// MongoAPIMetric.findAll.groupBy[String](_.url.get)
// }
//
// def getAllGroupedByDay() : Map[Date, List[APIMetric]] = {
// MongoAPIMetric.findAll.groupBy[Date](APIMetrics.getMetricDay)
// }
//
// def getAllGroupedByUserId() : Map[String, List[APIMetric]] = {
// MongoAPIMetric.findAll.groupBy[String](_.getUserId)
// }
override def getAllMetrics(queryParams: List[OBPQueryParam]): List[APIMetric] = {
MongoAPIMetric.findAll
}
override def bulkDeleteMetrics(): Boolean = ???
override def getAllAggregateMetricsFuture(queryParams: List[OBPQueryParam]): Future[Box[List[AggregateMetrics]]] = ???
override def getTopApisFuture(queryParams: List[OBPQueryParam]): Future[Box[List[TopApi]]] = ???
override def getTopConsumersFuture(queryParams: List[OBPQueryParam]): Future[Box[List[TopConsumer]]] = ???
}

View File

@ -1,249 +0,0 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.model.dataAccess
import java.util.Date
import code.api.util._
import code.model._
import code.util.Helper
import code.util.Helper.MdcLoggable
import com.mongodb.QueryBuilder
import com.openbankproject.commons.model._
import net.liftweb.common._
import net.liftweb.mapper.By
import net.liftweb.mongodb.BsonDSL._
import net.liftweb.mongodb.record.field.{DateField, ObjectIdPk, ObjectIdRefField}
import net.liftweb.mongodb.record.{MongoMetaRecord, MongoRecord}
import net.liftweb.mongodb.{Limit, Skip}
import net.liftweb.record.field.{DecimalField, StringField}
import scala.collection.immutable.List
class Account extends BankAccount with MongoRecord[Account] with ObjectIdPk[Account] with MdcLoggable{
def meta = Account
object accountBalance extends DecimalField(this, 0) {
//this is the legacy db field name
override def name = "balance"
}
object holder extends StringField(this, 255)
object accountNumber extends StringField(this, 255){
//this is the legacy db field name
override def name = "number"
}
object kind extends StringField(this, 255)
// object productCode extends StringField(this, 255)
object accountName extends StringField(this, 255){
//this is the legacy db field name
override def name = "name"
}
object permalink extends StringField(this, 255)
object bankID extends ObjectIdRefField(this, HostedBank)
object accountLabel extends StringField(this, 255){
//this is the legacy db field name
override def name = "label"
}
object accountCurrency extends StringField(this, 255){
//this is the legacy db field name
override def name = "currency"
}
object accountIban extends StringField(this, 255){
//this is the legacy db field name
override def name = "iban"
}
object accountLastUpdate extends DateField(this)
object mAccountRoutingScheme extends StringField(this, 255)
object mAccountRoutingAddress extends StringField(this, 255)
object mBranchId extends StringField(this, 255)
object mAccountRuleScheme1 extends StringField(this, 10)
object mAccountRuleValue1 extends DecimalField(this, 0)
object mAccountRuleScheme2 extends StringField(this, 10)
object mAccountRuleValue2 extends DecimalField(this, 0)
def transactionsForAccount: QueryBuilder = {
QueryBuilder
.start("obp_transaction.this_account.number")
.is(accountNumber.get)
//FIX: change that to use the bank identifier
.put("obp_transaction.this_account.bank.national_identifier")
.is(this.nationalIdentifier)
}
//find all the envelopes related to this account
def allEnvelopes: List[OBPEnvelope] = OBPEnvelope.findAll(transactionsForAccount.get)
def envelopes(queryParams: List[OBPQueryParam]): List[OBPEnvelope] = {
import com.mongodb.DBObject
import net.liftweb.mongodb.FindOption
val limit: Seq[Limit] = queryParams.collect { case OBPLimit(value) => Limit(value) }
val offset: Seq[Skip] = queryParams.collect { case OBPOffset(value) => Skip(value) }
val limitAndOffset: Seq[FindOption] = limit ++ offset
val fromDate: Option[OBPFromDate] = queryParams.collect { case param: OBPFromDate => param }.headOption
val toDate: Option[OBPToDate] = queryParams.collect { case param: OBPToDate => param }.headOption
val query: DBObject = {
val queryWithOptionalFromDate = fromDate.map{
date => {
transactionsForAccount
.put("obp_transaction.details.completed")
.greaterThanEquals(date.value)
}
}.getOrElse(transactionsForAccount)
val queryWithOptionalFromDateAndToDate = toDate.map{
date => {
queryWithOptionalFromDate
.put("obp_transaction.details.completed")
.lessThanEquals(date.value)
}
}.getOrElse(queryWithOptionalFromDate)
queryWithOptionalFromDateAndToDate.get
}
val defaultSortField = "obp_transaction.details.completed"
val orderingParams = queryParams
.collect { case param: OBPOrdering => param}
.headOption
val ordering: Option[DBObject] =
orderingParams.map{
o => {
QueryBuilder
.start(defaultSortField)
.is(o.order.orderValue)
.get
}
}
ordering match {
case Some(o) =>{
OBPEnvelope.findAll(query, o, limitAndOffset: _*)
}
case _ =>{
OBPEnvelope.findAll(query, limitAndOffset: _*)
}
}
}
override def bankId: BankId = {
bankID.obj match {
case Full(bank) => BankId(bank.permalink.get)
case _ => BankId("")
}
}
override def accountId : AccountId = AccountId(permalink.get)
def iban: Option[String] = {
val i = accountIban.get
if (i.isEmpty) None else Some(i)
}
override def currency: String = accountCurrency.get
override def number: String = accountNumber.get
override def balance: BigDecimal = accountBalance.get
override def name: String = accountName.get
override def accountType: String = kind.get
override def label: String = accountLabel.get
override def accountHolder: String = holder.get
override def lastUpdate: Date = accountLastUpdate.get
def accountRoutingScheme: String = mAccountRoutingScheme.get
def accountRoutingAddress: String = mAccountRoutingAddress.get
override def branchId: String = mBranchId.get
def createAccountRule(scheme: String, value: Long) = {
scheme match {
case s: String if s.equalsIgnoreCase("") == false =>
val v = Helper.smallestCurrencyUnitToBigDecimal(value, accountCurrency.get)
List(AccountRule(scheme, v.toString()))
case _ =>
Nil
}
}
override def accountRoutings: List[AccountRouting] = {
BankAccountRouting.findAll(
By(BankAccountRouting.BankId, this.bankId.value),
By(BankAccountRouting.AccountId, this.accountId.value)
).map(_.accountRouting) match {
case Nil => // This is the fallback if the BankAccountRouting failed
List(AccountRouting(mAccountRoutingScheme.get, mAccountRoutingAddress.get))
case everythingElseJustForward =>
everythingElseJustForward
}
}
override def accountRules: List[AccountRule] = createAccountRule(mAccountRuleScheme1.get, mAccountRuleValue1.get.toLong) :::
createAccountRule(mAccountRuleScheme2.get, mAccountRuleValue2.get.toLong)
}
object Account extends Account with MongoMetaRecord[Account] {
def init = createIndex((permalink.name -> 1) ~ (bankID.name -> 1), true)
}
class HostedBank extends Bank with MongoRecord[HostedBank] with ObjectIdPk[HostedBank]{
def meta = HostedBank
object name extends StringField(this, 255)
object alias extends StringField(this, 255)
object logoURL extends StringField(this, 255)
object website extends StringField(this, 255)
object email extends StringField(this, 255)
object permalink extends StringField(this, 255)
object swiftBIC extends StringField(this, 255)
object national_identifier extends StringField(this, 255)
object mBankRoutingScheme extends StringField(this, 255)
object mBankRoutingAddress extends StringField(this, 255)
def getAccount(bankAccountId: AccountId) : Box[Account] = {
Account.find((Account.permalink.name -> bankAccountId.value) ~ (Account.bankID.name -> id.get)) ?~ {"account " + bankAccountId +" not found at bank " + permalink}
}
def isAccount(bankAccountId : AccountId) : Boolean =
Account.count((Account.permalink.name -> bankAccountId.value) ~ (Account.bankID.name -> id.get)) == 1
override def bankId: BankId = BankId(permalink.get)
override def shortName: String = alias.get
override def fullName: String = name.get
override def logoUrl: String = logoURL.get
override def websiteUrl: String = website.get
override def swiftBic: String = swiftBIC.get
override def nationalIdentifier: String = national_identifier.get
override def bankRoutingScheme = mBankRoutingAddress.get
override def bankRoutingAddress = mBankRoutingAddress.get
}
object HostedBank extends HostedBank with MongoMetaRecord[HostedBank] {
def init = createIndex((permalink.name -> 1), true)
def find(bankId : BankId) : Box[HostedBank] = find(HostedBank.permalink.name -> bankId.value)
}

View File

@ -1,64 +0,0 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.model.dataAccess
import code.api.util.APIUtil
import code.metadata.narrative.OBPNarrativeInit
import code.metadata.wheretags.OBPWhereTagInit
import com.mongodb.MongoClient
import net.liftweb.util.ConnectionIdentifier
object AdminDb extends ConnectionIdentifier {
val jndiName = "admin"
}
object MongoConfig {
def init: Unit = {
import net.liftweb.mongodb.MongoDB
import com.mongodb.{Mongo, ServerAddress}
import net.liftweb.util.{Props, DefaultConnectionIdentifier}
val srvr = new ServerAddress(
APIUtil.getPropsValue("mongo.host", "localhost"),
APIUtil.getPropsAsIntValue("mongo.port", 27017)
)
val defaultDatabase = Props.mode match {
case Props.RunModes.Test => "test"
case _ => "OBP006"
}
MongoDB.defineDb(DefaultConnectionIdentifier, new MongoClient(srvr), APIUtil.getPropsValue("mongo.dbName", defaultDatabase))
MongoDB.defineDb(AdminDb, new MongoClient(srvr), "admin")
HostedBank.init
Account.init
OBPNarrativeInit.init
OBPWhereTagInit.init
}
}

View File

@ -1,408 +0,0 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.model.dataAccess
import code.util.Helper
import com.mongodb.QueryBuilder
import net.liftweb.mongodb.record.field._
import net.liftweb.mongodb.record.{BsonMetaRecord, BsonRecord, MongoMetaRecord, MongoRecord}
import net.liftweb.common.{Box, Empty, Failure}
import java.util.{Date, UUID}
import net.liftweb.record.field.{LongField, StringField}
import net.liftweb.json.JsonAST._
import code.model._
import code.util.Helper.MdcLoggable
import net.liftweb.record.field.{DecimalField, DoubleField}
import net.liftweb.util.FieldError
import org.bson.types.ObjectId
import scala.xml.Unparsed
import net.liftweb.json.JsonAST.JObject
import scala.Some
import net.liftweb.json.JsonAST.JString
import net.liftweb.common.Full
import net.liftweb.json.JsonAST.JField
import code.metadata.counterparties.MongoCounterparties
import com.openbankproject.commons.model.{AccountId, BankId, TransactionId}
/**
* "Current Account View"
curl -i -H "Content-Type: application/json" -X POST -d '[{
"obp_transaction":{
"this_account":{
"holder":"Music Pictures Limited",
"number":"123567",
"kind":"current",
"bank":{
"IBAN":"DE1235123612",
"national_identifier":"de.10010010",
"name":"Postbank"
}
},
"other_account":{
"holder":"Client 1",
"number":"123567",
"kind":"current",
"bank":{
"IBAN":"UK12222879",
"national_identifier":"uk.10010010",
"name":"HSBC"
}
},
"details":{
"type_en":"Transfer",
"type_de":"Überweisung",
"posted":{
"$dt":"2012-01-04T18:06:22.000Z"
},
"completed":{
"$dt":"2012-09-04T18:52:13.000Z"
},
"new_balance":{
"currency":"EUR",
"amount":"4323.45"
},
"value":{
"currency":"EUR",
"amount":"123.45"
},
"other_data":"9"
}
}
},
{
"obp_transaction":{
"this_account":{
"holder":"Music Pictures Limited",
"number":"123567",
"kind":"current",
"bank":{
"IBAN":"DE1235123612",
"national_identifier":"de.10010010",
"name":"Postbank"
}
},
"other_account":{
"holder":"Client 2",
"number":"123567",
"kind":"current",
"bank":{
"IBAN":"UK22222879",
"national_identifier":"uk.10010010",
"name":"HSBC"
}
},
"details":{
"type_en":"Transfer",
"type_de":"Überweisung",
"posted":{
"$dt":"2012-01-04T14:06:22.000Z"
},
"completed":{
"$dt":"2012-09-04T14:52:13.000Z"
},
"new_balance":{
"currency":"EUR",
"amount":"2222.45"
},
"value":{
"currency":"EUR",
"amount":"223.45"
},
"other_data":"9"
}
}
}]' http://localhost:8080/api/transactions
*/
// Seems to map to a collection of the plural name
class OBPEnvelope private() extends MongoRecord[OBPEnvelope] with ObjectIdPk[OBPEnvelope] with MdcLoggable with TransactionUUID {
def meta = OBPEnvelope
def theTransactionId = TransactionId(transactionId.get)
def theAccountId = theAccount.map(_.accountId).getOrElse(AccountId(""))
def theBankId = theAccount.map(_.bankId).getOrElse(BankId(""))
object transactionId extends StringField(this, 100) {
override def defaultValue = UUID.randomUUID.toString
}
// This creates a json attribute called "obp_transaction"
object obp_transaction extends BsonRecordField(this, OBPTransaction)
override def validate: List[FieldError] =
obp_transaction.get.validate ++
super.validate
object DateDescending extends Ordering[OBPEnvelope] {
def compare(e1: OBPEnvelope, e2: OBPEnvelope) = {
val date1 = e1.obp_transaction.get.details.get.completed.get
val date2 = e2.obp_transaction.get.details.get.completed.get
date1.compareTo(date2)
}
}
lazy val theAccount: Box[Account] = {
import net.liftweb.mongodb.BsonDSL._
val thisAcc = obp_transaction.get.this_account.get
val num = thisAcc.number.get
val bankNationalIdentifier = thisAcc.bank.get.national_identifier.get
for {
bank <- HostedBank.find((HostedBank.national_identifier.name -> bankNationalIdentifier))
bankMongoId : ObjectId = bank.id.get
account <- Account.find((Account.accountNumber.name -> num) ~ (Account.bankID.name -> bankMongoId))
} yield account
}
def orderByDateDescending = (e1: OBPEnvelope, e2: OBPEnvelope) => {
val date1 = e1.obp_transaction.get.details.get.completed.get
val date2 = e2.obp_transaction.get.details.get.completed.get
date1.after(date2)
}
}
object OBPEnvelope extends OBPEnvelope with MongoMetaRecord[OBPEnvelope] with MdcLoggable {
def envelopesFromJValue(jval: JValue) : Box[OBPEnvelope] = {
val createdBox = fromJValue(jval)
createdBox match {
case Full(created) =>
val errors = created.validate
if(errors.isEmpty) {
Full(created)
} else {
logger.warn("could not create a obp envelope.errors: ")
logger.warn(errors)
Empty
}
case Failure(msg, _, _) =>
Failure(s"could not create Envelope from JValue: $msg")
case _ =>
Failure(s"could not create Envelope from JValue")
}
}
}
class OBPTransaction private() extends BsonRecord[OBPTransaction]{
def meta = OBPTransaction
object this_account extends BsonRecordField(this, OBPAccount)
object other_account extends BsonRecordField(this, OBPAccount)
object details extends BsonRecordField(this, OBPDetails)
private def validateThisAccount: List[FieldError] = {
val accountNumber = this_account.get.number
val bankId = this_account.get.bank.get.national_identifier
val accountNumberError =
if(accountNumber.get.isEmpty)
Some(new FieldError(accountNumber, Unparsed("this bank account number is empty")))
else
None
val bankIdError =
if(bankId.get.isEmpty)
Some(new FieldError(bankId, Unparsed("this bank number is empty")))
else
None
List(accountNumberError, bankIdError).flatten
}
override def validate: List[FieldError] =
validateThisAccount ++
this_account.get.validate ++
other_account.get.validate ++
details.get.validate ++
super.validate
@deprecated(Helper.deprecatedJsonGenerationMessage, null)
def whenAddedJson(envelopeId : String) : JObject = {
JObject(List(JField("obp_transaction_uuid", JString(envelopeId)),
JField("this_account", this_account.get.whenAddedJson),
JField("other_account", other_account.get.whenAddedJson),
JField("details", details.get.whenAddedJson)))
}
}
object OBPTransaction extends OBPTransaction with BsonMetaRecord[OBPTransaction]
class OBPAccount private() extends BsonRecord[OBPAccount]{
def meta = OBPAccount
object holder extends StringField(this, 255){
override def required_? = false
override def optional_? = true
}
object number extends StringField(this, 255){
override def required_? = false
override def optional_? = true
}
object kind extends StringField(this, 255){
override def required_? = false
override def optional_? = true
}
object bank extends BsonRecordField(this, OBPBank)
override def validate: List[FieldError] =
holder.validate ++
number.validate ++
kind.validate ++
bank.validate ++
super.validate
/**
* @param moderatingAccount a temporary way to provide the obp account whose aliases should
* be used when displaying this account
*/
def whenAddedJson: JObject = {
JObject(List(JField("holder",
JObject(List(
JField("holder", JString(holder.get)),
JField("alias", JString("no"))))),
JField("number", JString(number.get)),
JField("kind", JString(kind.get)),
JField("bank", bank.get.whenAddedJson)))
}
}
object OBPAccount extends OBPAccount with BsonMetaRecord[OBPAccount]{
sealed abstract class AnAlias
case object APublicAlias extends AnAlias
case object APrivateAlias extends AnAlias
}
class OBPBank private() extends BsonRecord[OBPBank]{
def meta = OBPBank
object IBAN extends net.liftweb.record.field.StringField(this, 255)
object national_identifier extends net.liftweb.record.field.StringField(this, 255)
object name extends net.liftweb.record.field.StringField(this, 255)
override def validate: List[FieldError] =
IBAN.validate ++
national_identifier.validate ++
name.validate ++
super.validate
def whenAddedJson : JObject = {
JObject(List( JField("IBAN", JString(IBAN.get)),
JField("national_identifier", JString(national_identifier.get)),
JField("name", JString(name.get))))
}
}
object OBPBank extends OBPBank with BsonMetaRecord[OBPBank]
class OBPDetails private() extends BsonRecord[OBPDetails]{
def meta = OBPDetails
object kind extends net.liftweb.record.field.StringField(this, 255){
override def required_? = false
override def optional_? = true
}
object posted extends DateField(this)
object other_data extends net.liftweb.record.field.StringField(this, 5000){
override def required_? = false
override def optional_? = true
}
object new_balance extends BsonRecordField(this, OBPBalance)
object value extends BsonRecordField(this, OBPValue)
object completed extends DateField(this)
object label extends net.liftweb.record.field.StringField(this, 255){
override def required_? = false
override def optional_? = true
}
override def validate: List[FieldError] =
kind.validate ++
posted.validate ++
other_data.validate ++
new_balance.validate ++
value.validate ++
completed.validate ++
label.validate ++
super.validate
def formatDate(date : Date) : String = {
OBPDetails.formats.dateFormat.format(date)
}
def whenAddedJson : JObject = {
JObject(List( JField("type_en", JString(kind.get)),
JField("type", JString(kind.get)),
JField("posted", JString(formatDate(posted.get))),
JField("completed", JString(formatDate(completed.get))),
JField("other_data", JString(other_data.get)),
JField("new_balance", new_balance.get.whenAddedJson),
JField("value", value.get.whenAddedJson)))
}
}
object OBPDetails extends OBPDetails with BsonMetaRecord[OBPDetails]
class OBPBalance private() extends BsonRecord[OBPBalance]{
def meta = OBPBalance
object currency extends StringField(this, 5)
object amount extends DecimalField(this, 0) // ok to use decimal?
override def validate: List[FieldError] =
currency.validate ++
amount.validate ++
super.validate
def whenAddedJson : JObject = {
JObject(List( JField("currency", JString(currency.get)),
JField("amount", JString(amount.get.toString))))
}
}
object OBPBalance extends OBPBalance with BsonMetaRecord[OBPBalance]
class OBPValue private() extends BsonRecord[OBPValue]{
def meta = OBPValue
object currency extends net.liftweb.record.field.StringField(this, 5)
object amount extends net.liftweb.record.field.DecimalField(this, 0) // ok to use decimal?
def whenAddedJson : JObject = {
JObject(List( JField("currency", JString(currency.get)),
JField("amount", JString(amount.get.toString))))
}
}
object OBPValue extends OBPValue with BsonMetaRecord[OBPValue]

View File

@ -1,155 +0,0 @@
package code.sandbox
import code.metadata.counterparties.{MongoCounterparties, Metadata}
import code.model._
import code.model.dataAccess._
import net.liftweb.common._
import java.util.UUID
import net.liftweb.mapper.By
import net.liftweb.mongodb.record.MongoRecord
import net.liftweb.util.Helpers._
import org.bson.types.ObjectId
//An basic implementation of Saveable for MongoRecords
case class SaveableMongoObj[T <: MongoRecord[_]](value : T) extends Saveable[T] {
def save() = value.save(true)
}
/**
* Imports data into the format used by LocalRecordConnector (e.g. HostedBank)
*/
/*
Not currently using this connector so not updating it at the moment.
object LocalRecordConnectorDataImport extends OBPDataImport with CreateAuthUsers {
type BankType = HostedBank
type AccountType = Account
type TransactionType = OBPEnvelope
type MetadataType = Metadata
protected def createSaveableBanks(data : List[SandboxBankImport]) : Box[List[Saveable[BankType]]] = {
val hostedBanks = data.map(b => {
HostedBank.createRecord
.id(ObjectId.get)
.permalink(b.id)
.name(b.full_name)
.alias(b.short_name)
.website(b.website)
.logoURL(b.logo)
.national_identifier(b.id) //this needs to match up with what goes in the OBPEnvelopes
})
val validationErrors = hostedBanks.flatMap(_.validate)
if(!validationErrors.isEmpty) {
Failure(s"Errors: ${validationErrors.map(_.msg)}")
} else {
Full(hostedBanks.map(SaveableMongoObj(_)))
}
}
protected def createSaveableAccount(acc : SandboxAccountImport, banks : List[HostedBank]) : Box[Saveable[Account]] = {
def getHostedBank(acc : SandboxAccountImport) = Box(banks.find(b => b.permalink.get == acc.bank))
def asSaveableAccount(account : Account, hostedBank : HostedBank) = new Saveable[Account] {
val value = account
def save() = {
//this looks pointless, but what it is doing is refreshing the Account.bankID.obj reference, which
//is used by Account.bankId. If we don't refresh it here, Account.bankId will return BankId("")
account.bankID(account.bankID.get).save(true)
}
}
for {
hBank <- getHostedBank(acc) ?~ {
logger.warn("hosted bank not found")
"Server error"
}
balance <- tryo{BigDecimal(acc.balance.amount)} ?~ s"Invalid balance: ${acc.balance.amount}"
} yield {
val account = Account.createRecord
.permalink(acc.id)
.bankID(hBank.id.get)
.accountLabel(acc.label)
.accountCurrency(acc.balance.currency)
.accountBalance(balance)
.accountNumber(acc.number)
.kind(acc.`type`)
.accountIban(acc.IBAN)
asSaveableAccount(account, hBank)
}
}
override protected def createSaveableTransaction(t : SandboxTransactionImport, createdBanks : List[BankType], createdAccounts : List[AccountType]) :
Box[Saveable[TransactionType]] = {
val counterpartyHolder = t.counterparty.flatMap(_.name).getOrElse("")
for {
createdBank <- Box(createdBanks.find(b => b.permalink.get == t.this_account.bank)) ?~
s"Transaction this_account bank must be specified in import banks. Unspecified bank: ${t.this_account.bank}"
//have to compare a.bankID to createdBank.id instead of just checking a.bankId against t.this_account.bank as createdBank hasn't been
//saved so the a.bankId method (which involves a db lookup) will not work
createdAcc <- Box(createdAccounts.find(a => a.bankID.toString == createdBank.id.get.toString && a.accountId == AccountId(t.this_account.id))) ?~
s"Transaction this_account account must be specified in import accounts. Unspecified account id: ${t.this_account.id} at bank: ${t.this_account.bank}"
newBalanceValue <- tryo{BigDecimal(t.details.new_balance)} ?~ s"Invalid new balance: ${t.details.new_balance}"
tValue <- 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 {
//bankNationalIdentifier not available from createdAcc.bankNationalIdentifier as it hasn't been saved so we get it from createdBank
val obpThisAccountBank = OBPBank.createRecord
.national_identifier(createdBank.national_identifier.get)
val obpThisAccount = OBPAccount.createRecord
.holder(createdAcc.holder.get)
.number(createdAcc.accountNumber.get)
.kind(createdAcc.kind.get)
.bank(obpThisAccountBank)
val counterpartyAccountNumber = t.counterparty.flatMap(_.account_number)
val obpOtherAccount = OBPAccount.createRecord
.holder(counterpartyHolder)
.number(counterpartyAccountNumber.getOrElse(""))
val newBalance = OBPBalance.createRecord
.amount(newBalanceValue)
.currency(createdAcc.accountCurrency.get)
val transactionValue = OBPValue.createRecord
.amount(tValue)
.currency(createdAcc.accountCurrency.get)
val obpDetails = OBPDetails.createRecord
.completed(completedDate)
.posted(postedDate)
.kind(t.details.`type`)
.label(t.details.description)
.new_balance(newBalance)
.value(transactionValue)
val obpTransaction = OBPTransaction.createRecord
.details(obpDetails)
.this_account(obpThisAccount)
.other_account(obpOtherAccount)
val env = OBPEnvelope.createRecord
.transactionId(t.id)
.obp_transaction(obpTransaction)
SaveableMongoObj(env)
}
}
}
*/

View File

@ -98,7 +98,6 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Match
m == Nonce || m == code.model.Token || m == code.model.Consumer || m == AuthUser || m == ResourceUser
}
//drop database tables before
//MongoDB.getDb(DefaultMongoIdentifier).foreach(_.dropDatabase())
ToSchemify.models.filterNot(exclusion).foreach(_.bulkDelete_!!())
ToSchemify.modelsRemotedata.filterNot(exclusion).foreach(_.bulkDelete_!!())
//we need to delete the test uses manully here.

View File

@ -1,107 +0,0 @@
package code.setup
import java.util.Date
import code.model._
import code.model.dataAccess._
import com.mongodb.QueryBuilder
import net.liftweb.util.Helpers._
import code.api.util.ErrorMessages._
import com.openbankproject.commons.model.{AccountId, Bank, BankAccount, BankId}
import scala.math.BigDecimal
import scala.math.BigDecimal.RoundingMode
import scala.util.Random._
/**
* This trait is for Liftweb record, link to MangoDB....
*/
trait LocalRecordConnectorTestSetup extends TestConnectorSetupWithStandardPermissions {
override protected def createBank(id : String) : Bank = {
HostedBank.createRecord.
name(randomString(5)).
alias(randomString(5)).
permalink(id).
national_identifier(randomString(5)).
save(true)
}
override protected def createAccount(bankId: BankId, accountId : AccountId, currency : String) : BankAccount = {
val q = QueryBuilder.start(HostedBank.permalink.name).is(bankId.value).get()
val hostedBank = HostedBank.find(q).openOrThrowException(attemptedToOpenAnEmptyBox)
Account.createRecord.
accountBalance(900000000).
holder(randomString(4)).
accountNumber(randomString(4)).
kind(randomString(4)).
accountName(randomString(4)).
permalink(accountId.value).
bankID(hostedBank.id.get).
accountLabel(randomString(4)).
accountCurrency(currency).
save(true)
}
override protected def createTransaction(account: BankAccount, startDate: Date, finishDate: Date) = {
val thisAccountBank = OBPBank.createRecord.
IBAN(randomString(5)).
national_identifier(account.nationalIdentifier).
name(account.bankName)
val thisAccount = OBPAccount.createRecord.
holder(account.accountHolder).
number(account.number).
kind(account.accountType).
bank(thisAccountBank)
val otherAccountBank = OBPBank.createRecord.
IBAN(randomString(5)).
national_identifier(randomString(5)).
name(randomString(5))
val otherAccount = OBPAccount.createRecord.
holder(randomString(5)).
number(randomString(5)).
kind(randomString(5)).
bank(otherAccountBank)
val transactionAmount = BigDecimal(nextDouble * 1000).setScale(2,RoundingMode.HALF_UP)
val newBalance : OBPBalance = OBPBalance.createRecord.
currency(account.currency).
amount(account.balance + transactionAmount)
val newValue : OBPValue = OBPValue.createRecord.
currency(account.currency).
amount(transactionAmount)
val details ={
OBPDetails
.createRecord
.kind(randomString(5))
.posted(startDate)
.other_data(randomString(5))
.new_balance(newBalance)
.value(newValue)
.completed(finishDate)
.label(randomString(5))
}
val transaction = OBPTransaction.createRecord.
this_account(thisAccount).
other_account(otherAccount).
details(details)
val env = OBPEnvelope.createRecord.
obp_transaction(transaction).save(true)
//slightly ugly
account.asInstanceOf[Account].accountBalance(newBalance.amount.get).accountLastUpdate(now).save(true)
env.save(true)
}
override protected def createTransactionRequest(account: BankAccount) = Nil
}

View File

@ -8,8 +8,6 @@ import code.model.dataAccess._
import code.views.Views
import com.openbankproject.commons.model._
import net.liftweb.mapper.MetaMapper
import net.liftweb.mongodb._
import net.liftweb.util.DefaultConnectionIdentifier
import net.liftweb.util.Helpers._
/**
@ -40,9 +38,6 @@ trait TestConnectorSetupWithStandardPermissions extends TestConnectorSetup {
protected def wipeTestData(): Unit = {
//drop the mongo Database after each test
MongoDB.getDb(DefaultConnectionIdentifier).foreach(_.dropDatabase())
//returns true if the model should not be wiped after each test
def exclusion(m : MetaMapper[_]) = {
m == Nonce || m == Token || m == Consumer || m == AuthUser || m == ResourceUser