Merge pull request #409 from hongwei1/develop

Option to run Mapped table access on a remote machine separated by Akka #154 - Counterparties (WIP)
This commit is contained in:
Simon Redfern 2017-02-21 19:22:45 +01:00 committed by GitHub
commit 1c9f2ce184
8 changed files with 236 additions and 19 deletions

View File

@ -2,19 +2,21 @@ package code.metadata.counterparties
import net.liftweb.common.Box
import net.liftweb.util.SimpleInjector
import code.model.{AccountId, BankId, CounterpartyMetadata, Counterparty}
import code.model.{AccountId, BankId, Counterparty, CounterpartyMetadata}
import code.views.AkkaMapperViews
object Counterparties extends SimpleInjector {
val counterparties = new Inject(buildOne _) {}
def buildOne: Counterparties = MapperCounterparties
// def buildOne: Counterparties = AkkaMapperViews
}
trait Counterparties {
def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, otherParty : Counterparty) : CounterpartyMetadata
def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, otherParty : Counterparty) : Box[CounterpartyMetadata]
//get all counterparty metadatas for a single OBP account
def getMetadatas(originalPartyBankId: BankId, originalPartyAccountId : AccountId) : List[CounterpartyMetadata]
@ -64,4 +66,26 @@ trait CounterpartyTrait {
def otherBankRoutingAddress: String
def isBeneficiary : Boolean
}
}
class RemoteCounterpartiesCaseClasses {
case class getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, otherParty: Counterparty)
case class getMetadatas(originalPartyBankId: BankId, originalPartyAccountId: AccountId)
case class getMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, counterpartyMetadataId: String)
case class getCounterparty(counterPartyId: String)
case class getCounterpartyByIban(iban: String)
case class createCounterparty(
createdByUserId: String, thisBankId: String, thisAccountId: String, thisViewId: String,
name: String, otherBankId: String, otherAccountId: String, otherAccountRoutingScheme: String,
otherAccountRoutingAddress: String, otherBankRoutingScheme: String,
otherBankRoutingAddress: String, isBeneficiary: Boolean)
case class checkCounterpartyAvailable(name: String, thisBankId: String, thisAccountId: String, thisViewId: String)
}
object RemoteCounterpartiesCaseClasses extends RemoteCounterpartiesCaseClasses

View File

@ -10,7 +10,7 @@ import net.liftweb.mapper.{By, _}
import net.liftweb.util.Helpers.tryo
object MapperCounterparties extends Counterparties with Loggable {
override def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, otherParty: Counterparty): CounterpartyMetadata = {
override def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, otherParty: Counterparty): Box[CounterpartyMetadata] = {
/**
* Generates a new alias name that is guaranteed not to collide with any existing public alias names
@ -59,12 +59,12 @@ object MapperCounterparties extends Counterparties with Loggable {
val existing = findMappedCounterpartyMetadata(originalPartyBankId, originalPartyAccountId, otherParty)
existing match {
case Full(e) => e
case Full(e) => Full(e)
// Create it!
case _ => {
logger.debug("Before creating MappedCounterpartyMetadata")
// Store a record that contains counterparty information from the perspective of an account at a bank
MappedCounterpartyMetadata.create
Full(MappedCounterpartyMetadata.create
// Core info
.thisAccountBankId(originalPartyBankId.value)
.thisAccountId(originalPartyAccountId.value)
@ -74,7 +74,7 @@ object MapperCounterparties extends Counterparties with Loggable {
// otherParty.metadata is None at this point
//.imageUrl("www.example.com/image.jpg")
//.moreInfo("This is hardcoded moreInfo")
.saveMe
.saveMe)
}
}
}

View File

@ -27,7 +27,7 @@ object MongoCounterparties extends Counterparties with Loggable {
} yield m
}
def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, otherParty : Counterparty) : CounterpartyMetadata = {
def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId : AccountId, otherParty : Counterparty) : Box[CounterpartyMetadata] = {
/**
* This particular implementation requires the metadata id to be the same as the otherParty (OtherBankAccount) id
@ -40,7 +40,7 @@ object MongoCounterparties extends Counterparties with Loggable {
case _ => createMetadata(originalPartyBankId, originalPartyAccountId, otherParty.label, otherParty.thisAccountId.value)
}
metadata
Full(metadata)
}
/**

View File

@ -623,7 +623,7 @@ class Counterparty(
case Some(meta) =>
meta
case None =>
Counterparties.counterparties.vend.getOrCreateMetadata(otherBankId, otherAccountId, this)
Counterparties.counterparties.vend.getOrCreateMetadata(otherBankId, otherAccountId, this).openOrThrowException("Can not getOrCreateMetadata !")
}
}
}

View File

@ -11,7 +11,7 @@ object Users extends SimpleInjector {
val users = new Inject(buildOne _) {}
def buildOne: Users = LiftUsers
//def buildOne: Users = AkkaMapperViews
// def buildOne: Users = AkkaMapperViews
}

View File

@ -17,13 +17,15 @@ import akka.util.Timeout
import code.api.APIFailure
import code.model.dataAccess.ResourceUser
import code.users.{RemoteUserCaseClasses, Users}
import code.metadata.counterparties.{Counterparties, CounterpartyTrait, RemoteCounterpartiesCaseClasses}
object AkkaMapperViews extends Views with Users {
object AkkaMapperViews extends Views with Users with Counterparties{
val TIMEOUT = 10 seconds
val r = RemoteViewCaseClasses
val ru = RemoteUserCaseClasses
val rCounterparties = RemoteCounterpartiesCaseClasses
implicit val timeout = Timeout(10000 milliseconds)
val remote = ActorSystem("LookupSystem", ConfigFactory.load("remotelookup"))
@ -456,5 +458,110 @@ object AkkaMapperViews extends Views with Users {
}
res
}
override def getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, otherParty: Counterparty): Box[CounterpartyMetadata] = {
val res = try {
Full(
Await.result(
(viewsActor ? rCounterparties.getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, otherParty: Counterparty)).mapTo[CounterpartyMetadata],
TIMEOUT
)
)
}
catch {
case k: ActorKilledException => Empty ~> APIFailure(s"Can not getOrCreateMetadata", 404)
case e: Throwable => throw e
}
res
}
override def getMetadatas(originalPartyBankId: BankId, originalPartyAccountId: AccountId): List[CounterpartyMetadata] = {
val res = try {
Full(
Await.result(
(viewsActor ? rCounterparties.getMetadatas(originalPartyBankId: BankId, originalPartyAccountId: AccountId)).mapTo[List[CounterpartyMetadata]],
TIMEOUT
)
)
}
catch {
case k: ActorKilledException => Empty ~> APIFailure(s"Can not getMetadatas", 404)
case e: Throwable => throw e
}
res.get
}
override def getMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, counterpartyMetadataId: String): Box[CounterpartyMetadata] = {
val res = try {
Full(
Await.result(
(viewsActor ? rCounterparties.getMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, counterpartyMetadataId: String)).mapTo[CounterpartyMetadata],
TIMEOUT
)
)
}
catch {
case k: ActorKilledException => Empty ~> APIFailure(s"Can not getMetadata", 404)
case e: Throwable => throw e
}
res
}
override def getCounterparty(counterPartyId: String): Box[CounterpartyTrait] = {
val res = try {
Full(
Await.result(
(viewsActor ? rCounterparties.getCounterparty(counterPartyId: String)).mapTo[CounterpartyTrait],
TIMEOUT
)
)
}
catch {
case k: ActorKilledException => Empty ~> APIFailure(s"Can not getCounterparty", 404)
case e: Throwable => throw e
}
res
}
override def getCounterpartyByIban(iban: String): Box[CounterpartyTrait] = {
val res = try {
Full(
Await.result(
(viewsActor ? rCounterparties.getCounterpartyByIban(iban: String)).mapTo[CounterpartyTrait],
TIMEOUT
)
)
}
catch {
case k: ActorKilledException => Empty ~> APIFailure(s"Can not getCounterpartyByIban", 404)
case e: Throwable => throw e
}
res
}
override def createCounterparty(createdByUserId: String, thisBankId: String, thisAccountId: String, thisViewId: String, name: String, otherBankId: String, otherAccountId: String, otherAccountRoutingScheme: String, otherAccountRoutingAddress: String, otherBankRoutingScheme: String, otherBankRoutingAddress: String, isBeneficiary: Boolean): Box[CounterpartyTrait] = {
val res = try {
Full(
Await.result(
(viewsActor ? rCounterparties.createCounterparty(createdByUserId, thisBankId, thisAccountId, thisViewId, name, otherBankId, otherAccountId,
otherAccountRoutingScheme, otherAccountRoutingAddress, otherBankRoutingScheme, otherBankRoutingAddress,
isBeneficiary)).mapTo[CounterpartyTrait],
TIMEOUT
)
)
}
catch {
case k: ActorKilledException => Empty ~> APIFailure(s"Can not createCounterparty", 404)
case e: Throwable => throw e
}
res
}
override def checkCounterpartyAvailable(name: String, thisBankId: String, thisAccountId: String, thisViewId: String): Boolean = {
Await.result(
(viewsActor ? rCounterparties.checkCounterpartyAvailable(name: String, thisBankId: String, thisAccountId: String, thisViewId: String)).mapTo[Boolean],
TIMEOUT
)
}
}

View File

@ -15,6 +15,7 @@ import akka.util.Timeout
import bootstrap.liftweb.ToSchemify
import code.model.dataAccess.ResourceUser
import code.users.{LiftUsers, RemoteUserCaseClasses}
import code.metadata.counterparties.{CounterpartyTrait, MapperCounterparties, RemoteCounterpartiesCaseClasses}
class AkkaMapperViewsActor extends Actor {
@ -29,6 +30,9 @@ class AkkaMapperViewsActor extends Actor {
val vu = LiftUsers
val ru = RemoteUserCaseClasses
val vCounterparties = MapperCounterparties
val rCounterparties = RemoteCounterpartiesCaseClasses
def receive = {
case r.addPermissions(views : List[ViewUID], user : User) =>
@ -309,6 +313,88 @@ class AkkaMapperViewsActor extends Actor {
}
}.getOrElse( context.stop(sender) )
case rCounterparties.checkCounterpartyAvailable(name: String, thisBankId: String, thisAccountId: String, thisViewId: String)=>
logger.info("checkCounterpartyAvailable(" + name +", "+ thisBankId +", "+ thisAccountId +", "+ thisViewId +")")
sender ! vCounterparties.checkCounterpartyAvailable(name: String, thisBankId: String, thisAccountId: String, thisViewId: String)
case rCounterparties.createCounterparty(createdByUserId, thisBankId, thisAccountId, thisViewId, name, otherBankId, otherAccountId,
otherAccountRoutingScheme, otherAccountRoutingAddress, otherBankRoutingScheme, otherBankRoutingAddress,
isBeneficiary) =>
logger.info("createCounterparty(" + createdByUserId +", "+ thisBankId +", "+ thisAccountId +", "+ thisViewId +", "+ name +", "+ otherBankId + otherAccountId +", "
+ otherAccountRoutingScheme +", "+ otherAccountRoutingAddress +", "+ otherBankRoutingScheme +", "+ otherBankRoutingAddress +", "+ isBeneficiary+ ")")
{
for {
res <- vCounterparties.createCounterparty(createdByUserId, thisBankId, thisAccountId, thisViewId, name, otherBankId, otherAccountId,
otherAccountRoutingScheme, otherAccountRoutingAddress, otherBankRoutingScheme, otherBankRoutingAddress,
isBeneficiary)
} yield {
sender ! res.asInstanceOf[CounterpartyTrait]
}
}.getOrElse( context.stop(sender) )
case rCounterparties.getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, otherParty: Counterparty) =>
logger.info("getOrCreateMetadata(" + originalPartyBankId +", " +originalPartyAccountId+otherParty+")")
{
for {
res <- vCounterparties.getOrCreateMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, otherParty: Counterparty)
} yield {
sender ! res.asInstanceOf[CounterpartyMetadata]
}
}.getOrElse( context.stop(sender) )
case rCounterparties.getMetadatas(originalPartyBankId: BankId, originalPartyAccountId: AccountId) =>
logger.info("getOrCreateMetadata(" + originalPartyBankId +", "+originalPartyAccountId+")")
Full({
for {
res <- Full(vCounterparties.getMetadatas(originalPartyBankId: BankId, originalPartyAccountId: AccountId))
} yield {
sender ! res.asInstanceOf[List[CounterpartyMetadata]]
}
}).getOrElse(context.stop(sender))
case rCounterparties.getMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, counterpartyMetadataId: String) =>
logger.info("getMetadata(" + originalPartyBankId +", "+originalPartyAccountId+")")
{
for {
res <- vCounterparties.getMetadata(originalPartyBankId: BankId, originalPartyAccountId: AccountId, counterpartyMetadataId: String)
} yield {
sender ! res.asInstanceOf[CounterpartyMetadata]
}
}.getOrElse( context.stop(sender) )
case rCounterparties.getCounterparty(counterPartyId: String) =>
logger.info("getCounterparty(" + counterPartyId +")")
{
for {
res <- vCounterparties.getCounterparty(counterPartyId: String)
} yield {
sender ! res.asInstanceOf[CounterpartyTrait]
}
}.getOrElse( context.stop(sender) )
case rCounterparties.getCounterpartyByIban(iban: String) =>
logger.info("getOrCreateMetadata(" + iban +")")
{
for {
res <- vCounterparties.getCounterpartyByIban(iban: String)
} yield {
sender ! res.asInstanceOf[CounterpartyTrait]
}
}.getOrElse( context.stop(sender) )
case message => logger.info("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message)
}

View File

@ -10,7 +10,7 @@ import net.liftweb.json.Serialization.write
class CreateCounterpartyTest extends V210ServerSetup with DefaultUsers {
val customerPostJSON = PostCounterpartyJSON(
val counterpartyPostJSON = PostCounterpartyJSON(
name = "Company Salary",
other_bank_id ="gh.29.de",
other_account_id="007a268b-98bf-44ef-8f6a-9944618378cf",
@ -47,7 +47,7 @@ class CreateCounterpartyTest extends V210ServerSetup with DefaultUsers {
When("We make the request Create counterparty for an account")
val requestPost = (v2_1Request / "banks" / bankId.value / "accounts" / accountId.value / viewId.value / "counterparties" ).POST <@ (user1)
val responsePost = makePostRequest(requestPost, write(customerPostJSON))
val responsePost = makePostRequest(requestPost, write(counterpartyPostJSON))
Then("We should get a 200 and check all the fields")
responsePost.code should equal(200)
@ -62,13 +62,13 @@ class CreateCounterpartyTest extends V210ServerSetup with DefaultUsers {
case JString(i) => i
case _ => ""
}
accountRoutingAddress should equal(customerPostJSON.other_account_routing_address)
accountRoutingAddress should equal(counterpartyPostJSON.other_account_routing_address)
var bankRoutingScheme = (responsePost.body \ "other_bank_routing" \ "scheme" ) match {
case JString(i) => i
case _ => ""
}
bankRoutingScheme should equal(customerPostJSON.other_bank_routing_scheme)
bankRoutingScheme should equal(counterpartyPostJSON.other_bank_routing_scheme)
}
scenario("No BankAccount in Database") {
@ -82,7 +82,7 @@ class CreateCounterpartyTest extends V210ServerSetup with DefaultUsers {
grantAccessToView(authuser1, ownerView)
val requestPost = (v2_1Request / "banks" / bankId.value / "accounts" / accountId.value / viewId.value / "counterparties" ).POST <@ (user1)
val responsePost = makePostRequest(requestPost, write(customerPostJSON))
val responsePost = makePostRequest(requestPost, write(counterpartyPostJSON))
Then("We should get a 400")
responsePost.code should equal(400)
@ -100,10 +100,10 @@ class CreateCounterpartyTest extends V210ServerSetup with DefaultUsers {
When("We make the request Create counterparty for an account")
val requestPost = (v2_1Request / "banks" / bankId.value / "accounts" / accountId.value / viewId.value / "counterparties" ).POST <@ (user1)
var responsePost = makePostRequest(requestPost, write(customerPostJSON))
var responsePost = makePostRequest(requestPost, write(counterpartyPostJSON))
Then("We make the request again, the same name/bank_id/account_id/view_id")
responsePost = makePostRequest(requestPost, write(customerPostJSON))
responsePost = makePostRequest(requestPost, write(counterpartyPostJSON))
Then("We should get a 400 and check the error massage")
responsePost.code should equal(400)