From 413dcc14468fc1edc4adf92a8862ae3c6e367e1b Mon Sep 17 00:00:00 2001 From: Marko Milic Date: Thu, 30 Mar 2017 11:10:35 +0200 Subject: [PATCH 1/3] Nonce separated by Akka --- src/main/scala/bootstrap/liftweb/Boot.scala | 2 +- src/main/scala/code/api/oauth1.0.scala | 53 ++++++++++-------- src/main/scala/code/model/OAuth.scala | 50 +++++++++++++++++ src/main/scala/code/nonce/NonceProvider.scala | 45 ++++++++++++++++ .../code/remotedata/RemotedataActors.scala | 3 +- .../code/remotedata/RemotedataNonces.scala | 32 +++++++++++ .../remotedata/RemotedataNoncesActor.scala | 54 +++++++++++++++++++ .../code/snippet/OAuthAuthorisation.scala | 8 +-- 8 files changed, 218 insertions(+), 29 deletions(-) create mode 100644 src/main/scala/code/nonce/NonceProvider.scala create mode 100644 src/main/scala/code/remotedata/RemotedataNonces.scala create mode 100644 src/main/scala/code/remotedata/RemotedataNoncesActor.scala diff --git a/src/main/scala/bootstrap/liftweb/Boot.scala b/src/main/scala/bootstrap/liftweb/Boot.scala index 510a9ead3..2868ea307 100644 --- a/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/src/main/scala/bootstrap/liftweb/Boot.scala @@ -436,6 +436,7 @@ object ToSchemify { MappedUserCustomerLink, Consumer, Token, + Nonce, MappedCounterparty, MappedCounterpartyMetadata, MappedCounterpartyWhereTag, @@ -448,7 +449,6 @@ object ToSchemify { val models = List( AuthUser, Admin, - Nonce, MappedBank, MappedBankAccount, MappedTransaction, diff --git a/src/main/scala/code/api/oauth1.0.scala b/src/main/scala/code/api/oauth1.0.scala index 121b1e26c..51280fe83 100644 --- a/src/main/scala/code/api/oauth1.0.scala +++ b/src/main/scala/code/api/oauth1.0.scala @@ -30,15 +30,15 @@ import java.util.Date import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec -import code.token.Tokens import code.api.Constant._ import code.api.util.{APIUtil, ErrorMessages} import code.consumer.Consumers -import code.model.{Consumer, Nonce, TokenType, User} +import code.model.{Consumer, TokenType, User} +import code.nonce.Nonces +import code.token.Tokens import net.liftweb.common._ import net.liftweb.http.rest.RestHelper import net.liftweb.http.{InMemoryResponse, PostRequest, Req, S} -import net.liftweb.mapper.By import net.liftweb.util.Helpers import net.liftweb.util.Helpers.{tryo, _} @@ -219,13 +219,11 @@ object OAuthHandshake extends RestHelper with Loggable { * same timestamp, client credentials, and token combinations. */ val token = parameters.get("oauth_token") getOrElse "" - - Nonce.count( - By(Nonce.value,parameters.get("oauth_nonce").get), - By(Nonce.tokenKey, token), - By(Nonce.consumerkey,parameters.get("oauth_consumer_key").get), - By(Nonce.timestamp, new Date(parameters.get("oauth_timestamp").get.toLong)) - ) !=0 + Nonces.nonces.vend.countNonces(consumerKey = parameters.get("oauth_consumer_key").get, + tokenKey = token, + timestamp = new Date(parameters.get("oauth_timestamp").get.toLong), + value = parameters.get("oauth_nonce").get + ) !=0 } def correctSignature(OAuthparameters : Map[String, String], httpMethod : String) = { @@ -433,13 +431,18 @@ object OAuthHandshake extends RestHelper with Loggable { private def saveRequestToken(oAuthParameters : Map[String, String], tokenKey : String, tokenSecret : String) = { - import code.model.{Nonce, TokenType} + import code.model.TokenType - val nonce = Nonce.create - nonce.consumerkey(oAuthParameters.get("oauth_consumer_key").get) - nonce.timestamp(new Date(oAuthParameters.get("oauth_timestamp").get.toLong)) - nonce.value(oAuthParameters.get("oauth_nonce").get) - val nonceSaved = nonce.save() + val nonceSaved = Nonces.nonces.vend.createNonce( + id = None, + consumerKey = Some(oAuthParameters.get("oauth_consumer_key").get), + tokenKey = None, + timestamp = Some(new Date(oAuthParameters.get("oauth_timestamp").get.toLong)), + value = Some(oAuthParameters.get("oauth_nonce").get) + ) match { + case Full(_) => true + case _ => false + } val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(oAuthParameters.get("oauth_consumer_key").get) match { case Full(consumer) => Some(consumer.id.get) @@ -472,14 +475,18 @@ object OAuthHandshake extends RestHelper with Loggable { private def saveAuthorizationToken(oAuthParameters : Map[String, String], tokenKey : String, tokenSecret : String) = { - import code.model.{Nonce, TokenType} + import code.model.TokenType - val nonce = Nonce.create - nonce.consumerkey(oAuthParameters.get("oauth_consumer_key").get) - nonce.timestamp(new Date(oAuthParameters.get("oauth_timestamp").get.toLong)) - nonce.tokenKey(oAuthParameters.get("oauth_token").get) - nonce.value(oAuthParameters.get("oauth_nonce").get) - val nonceSaved = nonce.save() + val nonceSaved = Nonces.nonces.vend.createNonce( + id = None, + consumerKey = Some(oAuthParameters.get("oauth_consumer_key").get), + tokenKey = Some(oAuthParameters.get("oauth_token").get), + timestamp = Some(new Date(oAuthParameters.get("oauth_timestamp").get.toLong)), + value = Some(oAuthParameters.get("oauth_nonce").get) + ) match { + case Full(_) => true + case _ => false + } val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(oAuthParameters.get("oauth_consumer_key").get) match { case Full(consumer) => Some(consumer.id.get) diff --git a/src/main/scala/code/model/OAuth.scala b/src/main/scala/code/model/OAuth.scala index e1ffd5dc4..7f905c739 100644 --- a/src/main/scala/code/model/OAuth.scala +++ b/src/main/scala/code/model/OAuth.scala @@ -36,6 +36,7 @@ import code.token.TokensProvider import code.consumer.{Consumers, ConsumersProvider} import code.model.TokenType.TokenType import code.model.dataAccess.ResourceUser +import code.nonce.NoncesProvider import code.users.Users import net.liftweb.common._ import net.liftweb.http.S @@ -294,7 +295,56 @@ object Consumer extends Consumer with Loggable with LongKeyedMetaMapper[Consumer } +object MappedNonceProvider extends NoncesProvider { + override def createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]): Box[Nonce] = { + tryo { + val n = Nonce.create + id match { + case Some(v) => n.id(v) + case None => + } + consumerKey match { + case Some(v) => n.consumerkey(v) + case None => + } + tokenKey match { + case Some(v) => n.tokenKey(v) + case None => + } + timestamp match { + case Some(v) => n.timestamp(v) + case None => + } + value match { + case Some(v) => n.value(v) + case None => + } + val nonce = n.saveMe() + nonce + } + } + override def deleteExpiredNonces(currentDate: Date): Boolean = { + Nonce.findAll(By_<(Nonce.timestamp, currentDate)).forall(_.delete_!) + } + + override def countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String): Long = { + Nonce.count( + By(Nonce.value, value), + By(Nonce.tokenKey, tokenKey), + By(Nonce.consumerkey, consumerKey), + By(Nonce.timestamp, timestamp) + ) + } + +} class Nonce extends LongKeyedMapper[Nonce] { def getSingleton = Nonce diff --git a/src/main/scala/code/nonce/NonceProvider.scala b/src/main/scala/code/nonce/NonceProvider.scala new file mode 100644 index 000000000..dfa8a2dae --- /dev/null +++ b/src/main/scala/code/nonce/NonceProvider.scala @@ -0,0 +1,45 @@ +package code.nonce + +import java.util.Date + +import code.model.Nonce +import net.liftweb.util.SimpleInjector +import code.remotedata.RemotedataNonces +import net.liftweb.common.Box + + +object Nonces extends SimpleInjector { + + val nonces = new Inject(buildOne _) {} + + def buildOne: NoncesProvider = RemotedataNonces + +} + +trait NoncesProvider { + def createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]): Box[Nonce] + def deleteExpiredNonces(currentDate: Date): Boolean + def countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String): Long +} + +class RemotedataNoncesCaseClasses { + case class createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]) + case class deleteExpiredNonces(currentDate: Date) + case class countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String) +} + +object RemotedataNoncesCaseClasses extends RemotedataNoncesCaseClasses diff --git a/src/main/scala/code/remotedata/RemotedataActors.scala b/src/main/scala/code/remotedata/RemotedataActors.scala index c4e8505ad..503920600 100644 --- a/src/main/scala/code/remotedata/RemotedataActors.scala +++ b/src/main/scala/code/remotedata/RemotedataActors.scala @@ -96,7 +96,8 @@ object RemotedataActors extends Loggable { ActorProps[RemotedataConsumersActor] -> RemotedataConsumers.actorName, ActorProps[RemotedataTransactionRequestsActor] -> RemotedataTransactionRequests.actorName, ActorProps[RemotedataMetricsActor] -> RemotedataMetrics.actorName, - ActorProps[RemotedataTokensActor] -> RemotedataTokens.actorName + ActorProps[RemotedataTokensActor] -> RemotedataTokens.actorName, + ActorProps[RemotedataNoncesActor] -> RemotedataNonces.actorName ) actorsRemotedata.foreach { a => logger.info(actorSystem.actorOf(a._1, name = a._2)) } diff --git a/src/main/scala/code/remotedata/RemotedataNonces.scala b/src/main/scala/code/remotedata/RemotedataNonces.scala new file mode 100644 index 000000000..2ce99356c --- /dev/null +++ b/src/main/scala/code/remotedata/RemotedataNonces.scala @@ -0,0 +1,32 @@ +package code.remotedata + +import java.util.Date + +import code.model.Nonce +import code.nonce.{NoncesProvider, RemotedataNoncesCaseClasses} +import net.liftweb.common.Box +import akka.pattern.ask + + +object RemotedataNonces extends ActorInit with NoncesProvider { + + val cc = RemotedataNoncesCaseClasses + + def createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]): Box[Nonce] = + extractFutureToBox(actor ? cc.createNonce(id, consumerKey, tokenKey, timestamp, value)) + + def deleteExpiredNonces(currentDate: Date): Boolean = + extractFuture(actor ? cc.deleteExpiredNonces(currentDate)) + + def countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String): Long = + extractFuture(actor ? cc.countNonces(consumerKey, tokenKey, timestamp, value)) + + +} diff --git a/src/main/scala/code/remotedata/RemotedataNoncesActor.scala b/src/main/scala/code/remotedata/RemotedataNoncesActor.scala new file mode 100644 index 000000000..9561dfcc6 --- /dev/null +++ b/src/main/scala/code/remotedata/RemotedataNoncesActor.scala @@ -0,0 +1,54 @@ +package code.remotedata + +import java.util.Date + +import akka.actor.Actor +import akka.event.Logging +import code.model._ +import code.nonce.RemotedataNoncesCaseClasses + + +class RemotedataNoncesActor extends Actor with ActorHelper { + + val logger = Logging(context.system, this) + + val mapper = MappedNonceProvider + val cc = RemotedataNoncesCaseClasses + + def receive = { + + case cc.createNonce(id: Option[Long], + consumerKey: Option[String], + tokenKey: Option[String], + timestamp: Option[Date], + value: Option[String]) => + logger.debug("createNonce(" + id + ", " + + consumerKey+ ", " + + tokenKey + ", " + + timestamp + ", " + + value + ")") + sender ! extractResult(mapper.createNonce(id, consumerKey, tokenKey, timestamp, value)) + + case cc.deleteExpiredNonces(currentDate: Date) => + logger.debug("deleteExpiredNonces(" + currentDate +")") + sender ! extractResult(mapper.deleteExpiredNonces(currentDate)) + + case cc.countNonces(consumerKey: String, + tokenKey: String, + timestamp: Date, + value: String) => + logger.debug("countNonces(" + consumerKey + ", " + + tokenKey+ ", " + + timestamp + ", " + + value + ", " + + ")") + sender ! extractResult(mapper.countNonces(consumerKey, tokenKey, timestamp, value)) + + + case message => logger.warning("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message) + + } + +} + + diff --git a/src/main/scala/code/snippet/OAuthAuthorisation.scala b/src/main/scala/code/snippet/OAuthAuthorisation.scala index 1b6a43a97..9d53bfdc1 100644 --- a/src/main/scala/code/snippet/OAuthAuthorisation.scala +++ b/src/main/scala/code/snippet/OAuthAuthorisation.scala @@ -36,11 +36,12 @@ package code.snippet import java.util.Date -import code.token.Tokens import code.api.util.APIUtil import code.consumer.Consumers import code.model.dataAccess.AuthUser -import code.model.{Nonce, Token, TokenType} +import code.model.{Token, TokenType} +import code.nonce.Nonces +import code.token.Tokens import code.users.Users import code.util.Helper import code.util.Helper.NOOP_SELECTOR @@ -193,7 +194,6 @@ object OAuthAuthorisation { //looks for expired tokens and nonces and deletes them def dataBaseCleaner: Unit = { - import net.liftweb.mapper.By_< import net.liftweb.util.Schedule Schedule.schedule(dataBaseCleaner _, 1 hour) @@ -208,6 +208,6 @@ object OAuthAuthorisation { //delete expired tokens and nonces Tokens.tokens.vend.deleteExpiredTokens(currentDate) - Nonce.findAll(By_<(Nonce.timestamp, timeLimit)).foreach(t => t.delete_!) + Nonces.nonces.vend.deleteExpiredNonces(currentDate) } } \ No newline at end of file From 2802e1aaa9d540de9d230e08fefa7be16ac38e15 Mon Sep 17 00:00:00 2001 From: moule3053 Date: Thu, 30 Mar 2017 12:03:41 +0200 Subject: [PATCH 2/3] Changes to font styling throughout bnpparibas-irb sandbox page --- .../webapp/media/css/overrides/bnpp-irb.css | 75 +++++++++++++------ 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/src/main/webapp/media/css/overrides/bnpp-irb.css b/src/main/webapp/media/css/overrides/bnpp-irb.css index f5d7c03d8..ca662506f 100644 --- a/src/main/webapp/media/css/overrides/bnpp-irb.css +++ b/src/main/webapp/media/css/overrides/bnpp-irb.css @@ -23,6 +23,31 @@ margin: 20px 20px 0 0; } +p { + font-family: BNPPSansLight; +} + +a { + font-family: BNPPSansLight; +} + +.navlink { + + font-family: BNPPSansLight; + text-transform: uppercase; + + +} + +h1 { + font-family: BNPP-IRB-COND; + text-transform: uppercase; +} + +h2 { + font-family: BNPP-IRB-COND; +} + #main-about-box #main-about-buttons a { font-family: BNPP-IRB-Rounded2; font-size: 18px; @@ -35,17 +60,16 @@ #main-about-text h2 { text-transform: uppercase; - #font-family: "bu_sans", Arial, Helvetica, sans-serif; font-family: BNPP-IRB-COND; } #main-about-text p { - font-family: "bu_light",Arial, Helvetica, sans-serif; + font-family: BNPPSansLight; } #main-about p { color: white; - font-family: "bu_light",Arial, Helvetica, sans-serif; + font-family: BNPPSansLight; margin-top: 30px; margin-left: 30px; margin-right: 30px; @@ -54,7 +78,6 @@ #main-about h2 { color: white; - #font-family: "bu_sans", Arial, Helvetica, sans-serif; font-family: BNPP-IRB-COND; font-size: 32px; margin-top: 30px; @@ -69,8 +92,6 @@ } - - #footer2 { overflow: auto; @@ -79,8 +100,6 @@ padding: 0px 0 20px; } - - #footer2 #footer2-logo-left { margin: 0 0 0 450px; float: left; @@ -93,27 +112,41 @@ } #footer2 #footer2-middle-text { - font-size: 1em; - font-weight: bold; - margin: 5px 0 0 650px; - color: #000; - position: absolute; - font-family: BNPP-IRB-LIGHT; + font-size: 14px; + line-height: 23px; + margin: 5px 0 0 25px; + float: left; + font-family: BNPPSans; } #footer2-font { - font-family: BNPP-IRB-LIGHT; + font-family: BNPPSans; + font-size: 14px; +} + +#copyright { + font-family: BNPPSansLight; } #main-support { background-color: #24b3c7; } +#top-text { + font-family: BNPPSans; + font-size: 17px; + font-weight: normal; + margin: 23px 0 0 30px; + display: inline-block; + float: left; + +} + #webui_top_text { - position: absolute; - font-weight: bold; - margin: 45px 0 0 20px; - font-size: 1.4em; - padding-left: 10px; - font-family: BNPP-IRB-LIGHT; + color: #1d1d1b; + margin: 0; + font-size: 17px; + line-height: 31px; + font-weight: normal; + font-family: BNPPSans; } \ No newline at end of file From 0f6a2183a906b79218211c7dc48bd0d7a6d3d6ed Mon Sep 17 00:00:00 2001 From: hongwei1 Date: Thu, 30 Mar 2017 13:00:20 +0200 Subject: [PATCH 3/3] refectory the MessageDoc format #ensure that all outbound messages contain action, reqId and messageFormat - yet have other free form fields # can not use any nest subclasses in exampleOutboundMessage/exampleInboundMessage --- src/main/scala/code/api/util/APIUtil.scala | 41 +- .../KafkaJSONFactory_vMar2017.scala | 187 +++-- .../KafkaMappedConnector_vMar2017.scala | 757 ++++++++++-------- 3 files changed, 523 insertions(+), 462 deletions(-) diff --git a/src/main/scala/code/api/util/APIUtil.scala b/src/main/scala/code/api/util/APIUtil.scala index 314386c44..6550d0f01 100644 --- a/src/main/scala/code/api/util/APIUtil.scala +++ b/src/main/scala/code/api/util/APIUtil.scala @@ -616,31 +616,34 @@ object APIUtil extends Loggable { catalogs: Catalogs, tags: List[ResourceDocTag] ) - - - - - // TODO How to ensure that all outbound messages contain action and version - yet have other free form fields? - // Would we have to have a detail key? or can we keep it flat? - abstract class OutboundMessageBase { + + + /** + * + * This is the base class for all kafka outbound case class + * action and messageFormat are mandatory + * The optionalFields can be any other new fields . + */ + abstract class OutboundMessageBase( + optionalFields: String* + ) { def action: String def messageFormat: String } - - abstract class ExampleOutboundMessage ( - detail: JValue - ) extends OutboundMessageBase - - // Similar to above, how would we ensure we have messageId and errorCode in the exampleInboundMessage? + + abstract class InboundMessageBase( + optionalFields: String* + ) { + def errorCode: String + } // Used to document the KafkaMessage calls case class MessageDoc( - process: String, - messageFormat: String, - description: String, - exampleOutboundMessage: JValue, // TODO make this more formal see above. - exampleInboundMessage: JValue, // TODO Ditto: should probably always include errorCode, see above. - errorResponseMessages: List[JValue] + process: String, + messageFormat: String, + description: String, + exampleOutboundMessage: JValue, + exampleInboundMessage: JValue ) // Define relations between API end points. Used to create _links in the JSON and maybe later for API Explorer browsing diff --git a/src/main/scala/code/bankconnectors/KafkaJSONFactory_vMar2017.scala b/src/main/scala/code/bankconnectors/KafkaJSONFactory_vMar2017.scala index 64b37c970..5627e8de8 100644 --- a/src/main/scala/code/bankconnectors/KafkaJSONFactory_vMar2017.scala +++ b/src/main/scala/code/bankconnectors/KafkaJSONFactory_vMar2017.scala @@ -34,7 +34,7 @@ package code.bankconnectors import java.text.SimpleDateFormat import java.util.{Date, Locale} -import code.api.util.APIUtil.{MessageDoc} +import code.api.util.APIUtil.{InboundMessageBase, MessageDoc, OutboundMessageBase} import code.fx.FXRate import code.metadata.counterparties.CounterpartyTrait import code.model.dataAccess.MappedBankAccountData @@ -53,39 +53,40 @@ case class InboundAccountData( accounts: List[InboundAccount] ) -case class OutboundUserByUsernamePassword( +case class OutboundUserByUsernamePasswordBase( + messageFormat: String, action: String, - version: String, username: String, password: String -) +)extends OutboundMessageBase -case class OutboundUserAccountViews( +case class OutboundUserAccountViewsBase( + messageFormat: String, action: String, - version: String, username: String, userId: String, bankId: String -) +)extends OutboundMessageBase -case class OutboundBanks( + +case class OutboundBanksBase( + messageFormat: String, action: String, - version: String, username: String, userId: String -) +) extends OutboundMessageBase case class OUTTBank( + messageFormat: String, action: String, - version: String, bankId: String, userId: String, username: String -) +)extends OutboundMessageBase -case class OutboundChallengeThreshold( +case class OutboundChallengeThresholdBase( + messageFormat: String, action: String, - version: String, bankId: String, accountId: String, viewId: String, @@ -93,11 +94,11 @@ case class OutboundChallengeThreshold( currency: String, userId: String, username: String -) +) extends OutboundMessageBase -case class OutboundChargeLevel( +case class OutboundChargeLevelBase( + messageFormat: String, action: String, - version: String, bankId: String, accountId: String, viewId: String, @@ -105,78 +106,95 @@ case class OutboundChargeLevel( username: String, transactionRequestType: String, currency: String -) +) extends OutboundMessageBase -case class OutboundChallenge( +case class OutboundChallengeBase( + messageFormat: String, action: String, - version: String, bankId: String, accountId: String, userId: String, username: String, transactionRequestType: String, transactionRequestId: String -) +) extends OutboundMessageBase -case class OutboundChallengeAnswer( +case class OutboundChallengeAnswerBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, challengeId: String, hashOfSuppliedAnswer: String -) +) extends OutboundMessageBase -case class OutboundTransactionQuery( +case class OutboundTransactionQueryBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, bankId: String, accountId: String, transactionId: String -) +) extends OutboundMessageBase -case class OutboundTransactionsQueryWithParams( +case class OutboundTransactionsQueryWithParamsBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, bankId: String, accountId: String, queryParams: String -) +) extends OutboundMessageBase -case class OutboundBankAccount( +case class OutboundBankAccountBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, bankId: String, accountId: String -) +) extends OutboundMessageBase -case class OutboundBankAccounts( +case class OutboundBankAccountsBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, bankId: String, accountId: String -) +) extends OutboundMessageBase -case class OutboundAccountByNumber( +case class OutboundAccountByNumberBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, bankId: String, number: String -) +) extends OutboundMessageBase -case class OutboundSaveTransaction( +case class OutboundCounterpartyByIbanBase( + messageFormat: String, + action: String, + userId: String, + username: String, + otherAccountRoutingAddress: String, + otherAccountRoutingScheme: String +) extends OutboundMessageBase + +case class OutboundCounterpartyByCounterpartyIdBase( + messageFormat: String, + action: String, + userId: String, + username: String, + counterpartyId: String +) extends OutboundMessageBase + +case class OutboundSaveTransactionBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, @@ -204,57 +222,41 @@ case class OutboundSaveTransaction( toCounterpartyRoutingScheme: String, toCounterpartyBankRoutingAddress: String, toCounterpartyBankRoutingScheme: String -) +) extends OutboundMessageBase -case class OutboundTransactionRequestStatuses( - action: String, - version: String -) +case class OutboundTransactionRequestStatusesBase( + messageFormat: String, + action: String +) extends OutboundMessageBase -case class OutboundCurrentFxRate( +case class OutboundCurrentFxRateBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, fromCurrencyCode: String, toCurrencyCode: String -) +) extends OutboundMessageBase -case class OutboundTransactionRequestTypeCharge( +case class OutboundTransactionRequestTypeChargeBase( + messageFormat: String, action: String, - version: String, userId: String, username: String, bankId: String, accountId: String, viewId: String, transactionRequestType: String -) +) extends OutboundMessageBase case class InboundValidatedUser( + errorCode: String, email: String, displayName: String -) - - -case class OutboundCounterpartyByIban( - action: String, - version: String, - userId: String, - username: String, - otherAccountRoutingAddress: String, - otherAccountRoutingScheme: String -) - -case class OutboundCounterpartyByCounterpartyId( - action: String, - version: String, - userId: String, - username: String, - counterpartyId: String -) +) extends InboundMessageBase case class InboundCounterparty( + errorCode: String, name: String, createdByUserId: String, thisBankId: String, @@ -268,7 +270,7 @@ case class InboundCounterparty( otherBranchRoutingScheme: String, otherBranchRoutingAddress: String, isBeneficiary: Boolean -) +) extends InboundMessageBase case class CounterpartyTrait2(counterparty: InboundCounterparty) extends CounterpartyTrait { @@ -288,11 +290,12 @@ case class CounterpartyTrait2(counterparty: InboundCounterparty) extends Counter } case class InboundBank( + errorCode: String, bankId: String, name: String, logo: String, url: String -) +)extends InboundMessageBase case class Bank2(r: InboundBank) extends Bank { @@ -306,6 +309,7 @@ case class Bank2(r: InboundBank) extends Bank { } case class InboundAccount( + errorCode: String, accountId: String, bankId: String, label: String, @@ -318,7 +322,7 @@ case class InboundAccount( generatePublicView: Boolean, generateAccountantsView: Boolean, generateAuditorsView: Boolean -) +)extends InboundMessageBase case class BankAccount2(r: InboundAccount) extends BankAccount { @@ -345,12 +349,13 @@ case class BankAccount2(r: InboundAccount) extends BankAccount { } case class InboundFXRate( + errorCode: String, fromCurrencyCode: String, toCurrencyCode: String, conversionValue: Double, inverseConversionValue: Double, effectiveDate: String -) +)extends InboundMessageBase case class FXRate2(inboundFxRate: InboundFXRate) extends FXRate { @@ -363,12 +368,13 @@ case class FXRate2(inboundFxRate: InboundFXRate) extends FXRate { } case class InboundTransactionRequestTypeCharge( + errorCode: String, transactionRequestType: String, bankId: String, chargeCurrency: String, chargeAmount: String, chargeSummary: String -) +)extends InboundMessageBase case class TransactionRequestTypeCharge2(inboundTransactionRequestTypeCharge: InboundTransactionRequestTypeCharge) extends TransactionRequestTypeCharge { @@ -466,6 +472,7 @@ case class InboundLocation( //InboundTransaction --> InternalTransaction -->OutboundTransaction case class InternalTransaction( + errorCode: String, transactionId: String, accountId: String, amount: String, @@ -480,7 +487,7 @@ case class InternalTransaction( postedDate: String, `type`: String, userId: String -) +)extends InboundMessageBase case class InboundAtm( id: String, @@ -519,8 +526,9 @@ case class InboundCustomer( ) case class InboundTransactionId( + errorCode: String, transactionId: String -) +)extends InboundMessageBase case class OutboundTransaction( action: String, @@ -535,20 +543,27 @@ case class OutboundTransaction( transactionType: String) case class InboundChallengeLevel( + errorCode: String, limit: String, currency: String -) +)extends InboundMessageBase +case class InboundCreateChallange( + errorCode: String, + challengeId: String +)extends InboundMessageBase -case class OutboundCreateChallange(challengeId: String) - -case class InboundValidateChallangeAnswer(answer: String) +case class InboundValidateChallangeAnswer( + answer: String, + errorCode: String +)extends InboundMessageBase case class InboundChargeLevel( + errorCode: String, currency: String, amount: String -) +)extends InboundMessageBase ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -557,8 +572,7 @@ case class MessageDocJson( message_format: String, description: String, example_outbound_message: JValue, - example_inbound_message: JValue, - possible_error_messages: List[JValue] + example_inbound_message: JValue ) // Creates the json resource_docs @@ -576,8 +590,7 @@ object KafkaJSONFactory_vMar2017 { message_format = md.messageFormat, description = md.description, example_outbound_message = md.exampleOutboundMessage, - example_inbound_message = md.exampleInboundMessage, - possible_error_messages = md.errorResponseMessages + example_inbound_message = md.exampleInboundMessage ) } diff --git a/src/main/scala/code/bankconnectors/KafkaMappedConnector_vMar2017.scala b/src/main/scala/code/bankconnectors/KafkaMappedConnector_vMar2017.scala index 2c25994a7..513b187b7 100644 --- a/src/main/scala/code/bankconnectors/KafkaMappedConnector_vMar2017.scala +++ b/src/main/scala/code/bankconnectors/KafkaMappedConnector_vMar2017.scala @@ -107,27 +107,30 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { messageFormat = messageFormat, description = "getUser from kafka ", exampleOutboundMessage = Extraction.decompose( - OutboundUserByUsernamePassword( + OutboundUserByUsernamePasswordBase( + messageFormat = messageFormat, action = "obp.get.User", - version = messageFormat, username = "susan.uk.29@example.com", password = "2b78e8" ) ), exampleInboundMessage = Extraction.decompose( InboundValidatedUser( + errorCode = "OBPS-001: .... ", email = "susan.uk.29@example.com", displayName = "susan" ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) - def getUser(username: String, password: String): Box[InboundUser] = { + def getUser( + username: String, + password: String + ): Box[InboundUser] = { for { - req <- Full(OutboundUserByUsernamePassword( + req <- Full(OutboundUserByUsernamePasswordBase( action = "obp.get.User", - version = messageFormat, + messageFormat = messageFormat, username = username, password = password)) u <- tryo { cachedUser.getOrElseUpdate(req.toString, () => process(req).extract[InboundValidatedUser]) } @@ -144,16 +147,17 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { messageFormat = messageFormat, description = "updateUserAccountViews from kafka ", exampleOutboundMessage = Extraction.decompose( - OutboundUserAccountViews( - action = "obp.get.Accounts", - version = messageFormat, - username = "susan.uk.29@example.com", - userId = "c7b6cb47-cb96-4441-8801-35b57456753a", - bankId = "gh.29.uk" + OutboundUserAccountViewsBase( + action = "obp.get.Accounts", + messageFormat = messageFormat, + username = "susan.uk.29@example.com", + userId = "c7b6cb47-cb96-4441-8801-35b57456753a", + bankId = "gh.29.uk" ) ), exampleInboundMessage = Extraction.decompose( InboundAccount( + errorCode = "OBPS-001: .... ", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", bankId = "gh.29.uk", label = "Good", @@ -165,23 +169,25 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { owners = "Susan" :: " Frank" :: Nil, generatePublicView = true, generateAccountantsView = true, - generateAuditorsView = true) + generateAuditorsView = true + ) :: InboundAccount( - accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", - bankId = "gh.29.uk", - label = "Good", - number = "123", - `type` = "AC", - balanceAmount = "50", - balanceCurrency = "EUR", - iban = "12345", - owners = "Susan" :: " Frank" :: Nil, - generatePublicView = true, - generateAccountantsView = true, - generateAuditorsView = true) + errorCode = "OBPS-001: .... ", + accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", + bankId = "gh.29.uk", + label = "Good", + number = "123", + `type` = "AC", + balanceAmount = "50", + balanceCurrency = "EUR", + iban = "12345", + owners = "Susan" :: " Frank" :: Nil, + generatePublicView = true, + generateAccountantsView = true, + generateAuditorsView = true + ) :: Nil - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) def updateUserAccountViews( user: ResourceUser ) = { @@ -190,9 +196,9 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { logger.info(s"ObpJvm updateUserAccountViews for user.email ${user.email} user.name ${user.name} at bank ${bankId}") for { username <- tryo {user.name} - req <- Full(OutboundUserAccountViews( + req <- Full(OutboundUserAccountViewsBase( + messageFormat = messageFormat, action = "obp.get.Accounts", - version = messageFormat, username = user.name, userId = user.name, bankId = bankId)) @@ -233,35 +239,40 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { messageFormat = messageFormat, description = "getBanks", exampleOutboundMessage = Extraction.decompose( - OutboundBanks( + OutboundBanksBase( action = "obp.get.Banks", - version = messageFormat, + messageFormat = messageFormat, username = "susan.uk.29@example.com", userId = "c7b6cb47-cb96-4441-8801-35b57456753a" ) ), exampleInboundMessage = Extraction.decompose( InboundBank( + errorCode = "OBPS-001: .... ", bankId = "gh.29.uk", name = "sushan", logo = "TESOBE", - url = "https://tesobe.com/") + url = "https://tesobe.com/" + ) :: InboundBank( + errorCode = "OBPS-001: .... ", bankId = "gh.29.uk", name = "sushan", logo = "TESOBE", - url = "https://tesobe.com/") - :: Nil), - errorResponseMessages = emptyObjectJson :: Nil + url = "https://tesobe.com/" + ) + :: Nil + ) ) //gets banks handled by this connector override def getBanks: List[Bank] = { - val req = OutboundBanks( + val req = OutboundBanksBase( + messageFormat = messageFormat, action = "obp.get.Banks", - version = messageFormat, username = currentResourceUserId, - userId = AuthUser.getCurrentUserUsername) + userId = AuthUser.getCurrentUserUsername + ) logger.debug(s"Kafka getBanks says: req is: $req") @@ -269,7 +280,6 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { val rList = { cachedBanks.getOrElseUpdate( req.toString, () => process(req).extract[List[InboundBank]]) } - logger.debug(s"Kafka getBanks says rList is $rList") // Loop through list of responses and create entry for each @@ -282,14 +292,15 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { logger.debug(s"Kafka getBanks says res is $res") res } + messageDocs += MessageDoc( process = "obp.get.ChallengeThreshold", messageFormat = messageFormat, description = "getChallengeThreshold from kafka ", exampleOutboundMessage = Extraction.decompose( - OutboundChallengeThreshold( + OutboundChallengeThresholdBase( + messageFormat = messageFormat, action = "obp.get.ChallengeThreshold", - version = messageFormat, bankId = "gh.29.uk", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", viewId = "owner", @@ -301,19 +312,19 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ), exampleInboundMessage = Extraction.decompose( InboundChallengeLevel( + errorCode = "OBPS-001: .... ", limit = "1000", currency = "EUR" ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) // Gets current challenge level for transaction request override def getChallengeThreshold(bankId: String, accountId: String, viewId: String, transactionRequestType: String, currency: String, userId: String, username: String): AmountOfMoney = { // Create argument list - val req = OutboundChallengeThreshold( + val req = OutboundChallengeThresholdBase( action = "obp.get.ChallengeThreshold", - version = messageFormat, + messageFormat = messageFormat, bankId = bankId, accountId = accountId, viewId = viewId, @@ -335,44 +346,45 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { } } } - + messageDocs += MessageDoc( process = "obp.get.ChargeLevel", messageFormat = messageFormat, description = "ChargeLevel from kafka ", - exampleOutboundMessage = Extraction.decompose( - OutboundChargeLevel( - action = "obp.get.ChargeLevel", - version = messageFormat, - bankId = "gh.29.uk", - accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", - viewId = "owner", - userId = "c7b6cb47-cb96-4441-8801-35b57456753a", - username = "susan.uk.29@example.com", - transactionRequestType = "SANDBOX_TAN", - currency = "EUR" - ) + exampleOutboundMessage = Extraction.decompose(OutboundChargeLevelBase( + action = "obp.get.ChargeLevel", + messageFormat = messageFormat, + bankId = "gh.29.uk", + accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", + viewId = "owner", + userId = "c7b6cb47-cb96-4441-8801-35b57456753a", + username = "susan.uk.29@example.com", + transactionRequestType = "SANDBOX_TAN", + currency = "EUR" + ) ), exampleInboundMessage = Extraction.decompose( InboundChargeLevel( + errorCode = "OBPS-001: .... ", currency = "EUR", amount = "" ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) - - override def getChargeLevel(bankId: BankId, - accountId: AccountId, - viewId: ViewId, - userId: String, - username: String, - transactionRequestType: String, - currency: String): Box[AmountOfMoney] = { + + override def getChargeLevel( + bankId: BankId, + accountId: AccountId, + viewId: ViewId, + userId: String, + username: String, + transactionRequestType: String, + currency: String + ): Box[AmountOfMoney] = { // Create argument list - val req = OutboundChargeLevel( + val req = OutboundChargeLevelBase( action = "obp.get.ChargeLevel", - version = messageFormat, + messageFormat = messageFormat, bankId = bankId.value, accountId = accountId.value, viewId = viewId.value, @@ -393,15 +405,15 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { } Full(chargeValue) } - + messageDocs += MessageDoc( process = "obp.create.Challenge", messageFormat = messageFormat, description = "CreateChallenge from kafka ", exampleOutboundMessage = Extraction.decompose( - OutboundChallenge( + OutboundChallengeBase( action = "obp.create.Challenge", - version = messageFormat, + messageFormat = messageFormat, bankId = "gh.29.uk", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", userId = "c7b6cb47-cb96-4441-8801-35b57456753a", @@ -411,50 +423,50 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ) ), exampleInboundMessage = Extraction.decompose( - OutboundChallenge( - action = "obp.create.Challenge", - version = messageFormat, - bankId = "gh.29.uk", - accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", - userId = "c7b6cb47-cb96-4441-8801-35b57456753a", - username = "susan.uk.29@example.com", - transactionRequestType = "SANDBOX_TAN", - transactionRequestId = "1234567" + InboundCreateChallange( + errorCode = "OBPS-001: .... ", + challengeId = "1234567" ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) - //TODO confused OutboundChallenge used for InboundChallenge, this should be changed ?? - override def createChallenge(bankId: BankId, accountId: AccountId, userId: String, transactionRequestType: TransactionRequestType, transactionRequestId: String) : Box[String] = { + override def createChallenge( + bankId: BankId, + accountId: AccountId, + userId: String, + transactionRequestType: TransactionRequestType, + transactionRequestId: String + ): Box[String] = { // Create argument list - val req = OutboundChallenge( + val req = OutboundChallengeBase( + messageFormat = messageFormat, action = "obp.create.Challenge", - version = messageFormat, bankId = bankId.value, accountId = accountId.value, userId = userId, username = AuthUser.getCurrentUserUsername, transactionRequestType = transactionRequestType.value, - transactionRequestId = transactionRequestId) - - val r: Option[OutboundCreateChallange] = process(req).extractOpt[OutboundCreateChallange] + transactionRequestId = transactionRequestId + ) + + val r: Option[InboundCreateChallange] = process(req + ).extractOpt[InboundCreateChallange] // Return result r match { // Check does the response data match the requested data - case Some(x) => Full(x.challengeId) - case _ => Empty + case Some(x) => Full(x.challengeId) + case _ => Empty } } - + messageDocs += MessageDoc( process = "obp.validate.ChallengeAnswer", messageFormat = messageFormat, description = "validateChallengeAnswer from kafka ", exampleOutboundMessage = Extraction.decompose( - OutboundChallengeAnswer( + OutboundChallengeAnswerBase( + messageFormat = messageFormat, action = "obp.validate.ChallengeAnswer", - version = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", challengeId = "1234", @@ -462,15 +474,20 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ) ), exampleInboundMessage = Extraction.decompose( - InboundValidateChallangeAnswer(answer = "") - ), - errorResponseMessages = emptyObjectJson :: Nil + InboundValidateChallangeAnswer( + errorCode = "OBPS-001: .... ", + answer = "" + ) + ) ) - override def validateChallengeAnswer(challengeId: String, hashOfSuppliedAnswer: String) : Box[Boolean] = { + override def validateChallengeAnswer( + challengeId: String, + hashOfSuppliedAnswer: String + ): Box[Boolean] = { // Create argument list - val req = OutboundChallengeAnswer( + val req = OutboundChallengeAnswerBase( + messageFormat = messageFormat, action = "obp.validate.ChallengeAnswer", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, challengeId = challengeId, @@ -484,7 +501,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { case _ => Empty } } - + messageDocs += MessageDoc( process = "obp.get.Bank", messageFormat = messageFormat, @@ -492,7 +509,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { exampleOutboundMessage = Extraction.decompose( OUTTBank( action = "obp.get.Bank", - version = messageFormat, + messageFormat = messageFormat, bankId = "gh.29.uk", userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com" @@ -500,19 +517,20 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ), exampleInboundMessage = Extraction.decompose( InboundBank( + + errorCode = "OBPS-001: .... ", bankId = "gh.29.uk", name = "sushan", logo = "TESOBE", url = "https://tesobe.com/" ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) override def getBank(bankid: BankId): Box[Bank] = { // Create argument list val req = OUTTBank( + messageFormat = messageFormat, action = "obp.get.Bank", - version = messageFormat, bankId = bankid.toString, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername) @@ -523,15 +541,15 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { // Return result Full(new Bank2(r)) } - + messageDocs += MessageDoc( process = "obp.get.Transaction", messageFormat = messageFormat, description = "getTransaction from kafka ", exampleOutboundMessage = Extraction.decompose( - OutboundTransactionQuery( + OutboundTransactionQueryBase( action = "obp.get.Transaction", - version = messageFormat, + messageFormat = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", bankId = "gh.29.uk", @@ -541,6 +559,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ), exampleInboundMessage = Extraction.decompose( InternalTransaction( + errorCode = "OBPS-001: .... ", transactionId = "1234", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", amount = "100", @@ -556,14 +575,13 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { `type` = "AC", userId = "1234" ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) // Gets transaction identified by bankid, accountid and transactionId def getTransaction(bankId: BankId, accountId: AccountId, transactionId: TransactionId): Box[Transaction] = { - val req = OutboundTransactionQuery( + val req = OutboundTransactionQueryBase( + messageFormat = messageFormat, action = "obp.get.Transaction", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, bankId = bankId.toString, @@ -580,15 +598,15 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { } } - + messageDocs += MessageDoc( process = "obp.get.Transactions", messageFormat = messageFormat, description = "getTransactions from kafka", exampleOutboundMessage = Extraction.decompose( - OutboundTransactionsQueryWithParams( + OutboundTransactionsQueryWithParamsBase( + messageFormat = messageFormat, action = "obp.get.Transactions", - version = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", bankId = "gh.29.uk", @@ -598,6 +616,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ), exampleInboundMessage = Extraction.decompose( InternalTransaction( + errorCode = "OBPS-001: .... ", transactionId = "1234", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", amount = "100", @@ -613,6 +632,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { `type` = "AC", userId = "1234" ) :: InternalTransaction( + errorCode = "OBPS-001: .... ", transactionId = "1234", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", amount = "100", @@ -628,8 +648,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { `type` = "AC", userId = "1234" ) :: Nil - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) //TODO, this action is different from method name override def getTransactions(bankId: BankId, accountId: AccountId, queryParams: OBPQueryParam*): Box[List[Transaction]] = { @@ -649,9 +668,9 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { //TODO no filter now. val mapperParams = Seq(By(MappedTransaction.bank, bankId.value), By(MappedTransaction.account, accountId.value)) ++ optionalParams - val req = OutboundTransactionsQueryWithParams( + val req = OutboundTransactionsQueryWithParamsBase( + messageFormat = messageFormat, action = "obp.get.Transactions", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, bankId = bankId.toString, @@ -673,15 +692,15 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { Full(res) //TODO is this needed updateAccountTransactions(bankId, accountId) } - + messageDocs += MessageDoc( process = "obp.get.Account", messageFormat = messageFormat, description = "getBankAccount from kafka", exampleOutboundMessage = Extraction.decompose( - OutboundBankAccount( + OutboundBankAccountBase( action = "obp.get.Account", - version = messageFormat, + messageFormat = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", bankId = "gh.29.uk", @@ -690,6 +709,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ), exampleInboundMessage = Extraction.decompose( InboundAccount( + errorCode = "OBPS-001: .... ", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", bankId = "gh.29.uk", label = "Good", @@ -703,18 +723,18 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { generateAccountantsView = true, generateAuditorsView = true ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) override def getBankAccount(bankId: BankId, accountId: AccountId): Box[BankAccount2] = { // Generate random uuid to be used as request-response match id - val req = OutboundBankAccount( + val req = OutboundBankAccountBase( action = "obp.get.Account", - version = messageFormat, + messageFormat = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, bankId = bankId.toString, - accountId = accountId.value) + accountId = accountId.value + ) // Since result is single account, we need only first list entry implicit val formats = net.liftweb.json.DefaultFormats @@ -730,23 +750,24 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { Full(new BankAccount2(r)) } - + messageDocs += MessageDoc( process = "obp.get.Accounts", messageFormat = messageFormat, description = "getBankAccounts from kafka", exampleOutboundMessage = Extraction.decompose( - OutboundBankAccounts( + OutboundBankAccountsBase( + messageFormat = messageFormat, action = "obp.get.Accounts", - version = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", bankId = "gh.29.uk", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0" ) - ), // TODO Why do we have accountId here if querying accounts? + ), exampleInboundMessage = Extraction.decompose( InboundAccount( + errorCode = "OBPS-001: .... ", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", bankId = "gh.29.uk", label = "Good", @@ -760,6 +781,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { generateAccountantsView = true, generateAuditorsView = true ) :: InboundAccount( + errorCode = "OBPS-001: .... ", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", bankId = "gh.29.uk", label = "Good", @@ -773,8 +795,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { generateAccountantsView = true, generateAuditorsView = true ) :: Nil - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) override def getBankAccounts(accts: List[(BankId, AccountId)]): List[BankAccount2] = { val primaryUserIdentifier = AuthUser.getCurrentUserUsername @@ -783,9 +804,9 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { logger.info (s"KafkaMappedConnnector.getBankAccounts with params ${a._1.value} and ${a._2.value} and primaryUserIdentifier is $primaryUserIdentifier") - val req = OutboundBankAccounts( + val req = OutboundBankAccountsBase( + messageFormat = messageFormat, action = "obp.get.Accounts", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, bankId = a._1.value, @@ -816,9 +837,9 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { messageFormat = messageFormat, description = "getAccountByNumber from kafka", exampleOutboundMessage = Extraction.decompose( - OutboundAccountByNumber( + OutboundAccountByNumberBase( action = "obp.get.Account", - version = messageFormat, + messageFormat = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", bankId = "gh.29.uk", @@ -827,6 +848,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ), exampleInboundMessage = Extraction.decompose( InboundAccount( + errorCode = "OBPS-001: .... ", accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", bankId = "gh.29.uk", label = "Good", @@ -840,15 +862,14 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { generateAccountantsView = true, generateAuditorsView = true ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) private def getAccountByNumber(bankId : BankId, number : String) : Box[AccountType] = { // Generate random uuid to be used as request-respose match id - val req = OutboundAccountByNumber( + val req = OutboundAccountByNumberBase( + messageFormat = messageFormat, action = "obp.get.Account", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, bankId = bankId.toString, @@ -877,23 +898,24 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { //note: kafka mode just used the mapper data LocalMappedConnector.getCounterparty(thisBankId, thisAccountId, couterpartyId) } - - + + messageDocs += MessageDoc( process = "obp.get.CounterpartyByCounterpartyId", messageFormat = messageFormat, description = "getCounterpartyByCounterpartyId from kafka ", exampleOutboundMessage = Extraction.decompose( - OutboundCounterpartyByCounterpartyId( + OutboundCounterpartyByCounterpartyIdBase( + messageFormat = messageFormat, action = "obp.get.CounterpartyByCounterpartyId", - version = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", - counterpartyId = "" + counterpartyId = "12344" ) ), exampleInboundMessage = Extraction.decompose( InboundCounterparty( + errorCode = "OBPS-001: .... ", name = "sushan", createdByUserId = "12345", thisBankId = "gh.29.uk", @@ -905,20 +927,19 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { otherBankRoutingAddress = "1234", otherAccountRoutingAddress = "1234", otherBranchRoutingScheme = "OBP", - otherBranchRoutingAddress ="Berlin", + otherBranchRoutingAddress = "Berlin", isBeneficiary = true ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) override def getCounterpartyByCounterpartyId(counterpartyId: CounterpartyId): Box[CounterpartyTrait] = { if (Props.getBool("get_counterparties_from_OBP_DB", true)) { Counterparties.counterparties.vend.getCounterparty(counterpartyId.value) } else { - val req = OutboundCounterpartyByCounterpartyId( + val req = OutboundCounterpartyByCounterpartyIdBase( + messageFormat = messageFormat, action = "obp.get.CounterpartyByCounterpartyId", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, counterpartyId = counterpartyId.toString @@ -931,15 +952,15 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { Full(CounterpartyTrait2(r)) } } - + messageDocs += MessageDoc( process = "obp.get.CounterpartyByIban", messageFormat = messageFormat, description = "getCounterpartyByIban from kafka ", exampleOutboundMessage = Extraction.decompose( - OutboundCounterpartyByIban( + OutboundCounterpartyByIbanBase( + messageFormat = messageFormat, action = "obp.get.CounterpartyByIban", - version = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", otherAccountRoutingAddress = "1234", @@ -949,6 +970,7 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { exampleInboundMessage = Extraction.decompose( CounterpartyTrait2( InboundCounterparty( + errorCode = "OBPS-001: .... ", name = "sushan", createdByUserId = "12345", thisBankId = "gh.29.uk", @@ -960,21 +982,20 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { otherBankRoutingAddress = "1234", otherAccountRoutingAddress = "1234", otherBranchRoutingScheme = "OBP", - otherBranchRoutingAddress ="Berlin", + otherBranchRoutingAddress = "Berlin", isBeneficiary = true ) ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) override def getCounterpartyByIban(iban: String): Box[CounterpartyTrait] = { if (Props.getBool("get_counterparties_from_OBP_DB", true)) { Counterparties.counterparties.vend.getCounterpartyByIban(iban) } else { - val req = OutboundCounterpartyByIban( + val req = OutboundCounterpartyByIbanBase( + messageFormat = messageFormat, action = "obp.get.CounterpartyByIban", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, otherAccountRoutingAddress = iban, @@ -984,68 +1005,15 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { Full(CounterpartyTrait2(r)) } } - - override def getCounterparties(thisBankId: BankId, thisAccountId: AccountId,viewId :ViewId): Box[List[CounterpartyTrait]] = { - //note: kafka mode just used the mapper data - LocalMappedConnector.getCounterparties(thisBankId, thisAccountId, viewId) - } - override def getPhysicalCards(user: User): List[PhysicalCard] = - List() - - override def getPhysicalCardsForBank(bank: Bank, user: User): List[PhysicalCard] = - List() - - def AddPhysicalCard(bankCardNumber: String, - nameOnCard: String, - issueNumber: String, - serialNumber: String, - validFrom: Date, - expires: Date, - enabled: Boolean, - cancelled: Boolean, - onHotList: Boolean, - technology: String, - networks: List[String], - allows: List[String], - accountId: String, - bankId: String, - replacement: Option[CardReplacementInfo], - pinResets: List[PinResetInfo], - collected: Option[CardCollectionInfo], - posted: Option[CardPostedInfo] - ) : Box[PhysicalCard] = { - Empty - } - - - protected override def makePaymentImpl(fromAccount: BankAccount2, - toAccount: BankAccount2, - toCounterparty: CounterpartyTrait, - amt: BigDecimal, - description: String, - transactionRequestType: TransactionRequestType, - chargePolicy: String): Box[TransactionId] = { - - val sentTransactionId = saveTransaction(fromAccount, - toAccount, - toCounterparty, - amt, - description, - transactionRequestType, - chargePolicy) - - sentTransactionId - } - - + messageDocs += MessageDoc( process = "obp.put.Transaction", messageFormat = messageFormat, description = "saveTransaction from kafka", exampleOutboundMessage = Extraction.decompose( - OutboundSaveTransaction( + OutboundSaveTransactionBase( action = "obp.put.Transaction", - version = messageFormat, + messageFormat = messageFormat, userId = "c7b6cb47-cb96-4441-8801-35b57456753a", username = "susan.uk.29@example.com", @@ -1076,9 +1044,12 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { ) ), exampleInboundMessage = Extraction.decompose( - InboundTransactionId(transactionId = "1234") - ), - errorResponseMessages = emptyObjectJson :: Nil + InboundTransactionId( + + errorCode = "OBPS-001: .... ", + transactionId = "1234" + ) + ) ) /** @@ -1098,9 +1069,9 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { val req = if (toAccount != null && toCounterparty == null) { - OutboundSaveTransaction( + OutboundSaveTransactionBase( + messageFormat = messageFormat, action = "obp.put.Transaction", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, @@ -1129,9 +1100,9 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { toCounterpartyBankRoutingAddress = toAccount.bankId.value, toCounterpartyBankRoutingScheme = "OBP") } else { - OutboundSaveTransaction( + OutboundSaveTransactionBase( + messageFormat = messageFormat, action = "obp.put.Transaction", - version = messageFormat, userId = currentResourceUserId, username = AuthUser.getCurrentUserUsername, @@ -1150,7 +1121,6 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { transactionChargeCurrency = fromAccount.currency, // TODO get correct charge currency transactionDescription = description, transactionPostedDate = postedDate, - // toAccount or toCounterparty toCounterpartyId = toCounterparty.counterpartyId, toCounterpartyName = toCounterparty.name, @@ -1180,9 +1150,9 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { messageFormat = messageFormat, description = "getTransactionRequestStatusesImpl from kafka", exampleOutboundMessage = Extraction.decompose( - OutboundTransactionRequestStatuses( - action = "obp.get.TransactionRequestStatusesImpl", - version = messageFormat + OutboundTransactionRequestStatusesBase( + messageFormat = messageFormat, + action = "obp.get.TransactionRequestStatusesImpl" ) ), exampleInboundMessage = Extraction.decompose( @@ -1198,17 +1168,13 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { transactionTimestamp = "" ) :: Nil ) - ), - errorResponseMessages = emptyObjectJson :: Nil + ) ) - /* - Transaction Requests - */ override def getTransactionRequestStatusesImpl() : Box[TransactionRequestStatus] = { logger.info(s"tKafka getTransactionRequestStatusesImpl sart: ") - val req = OutboundTransactionRequestStatuses( - action = "obp.get.TransactionRequestStatusesImpl", - version = messageFormat + val req = OutboundTransactionRequestStatusesBase( + messageFormat = messageFormat, + action = "obp.get.TransactionRequestStatusesImpl" ) //TODO need more clear error handling to user, if it is Empty or Error now,all response Empty. val r = try{ @@ -1221,7 +1187,184 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { logger.info(s"Kafka getTransactionRequestStatusesImpl response: ${r.toString}") r } - + + messageDocs += MessageDoc( + process = "obp.get.CurrentFxRate", + messageFormat = messageFormat, + description = "getCurrentFxRate from kafka", + exampleOutboundMessage = Extraction.decompose( + OutboundCurrentFxRateBase( + action = "obp.get.CurrentFxRate", + messageFormat = messageFormat, + userId = "c7b6cb47-cb96-4441-8801-35b57456753a", + username = "susan.uk.29@example.com", + fromCurrencyCode = "1234", + toCurrencyCode = "" + ) + ), + exampleInboundMessage = Extraction.decompose( + InboundFXRate( + errorCode = "OBPS-001: .... ", + fromCurrencyCode = "1234", + toCurrencyCode = "1234", + conversionValue = 123.44, + inverseConversionValue = 123.44, + effectiveDate = "" + ) + ) + ) + // get the latest FXRate specified by fromCurrencyCode and toCurrencyCode. + override def getCurrentFxRate(fromCurrencyCode: String, toCurrencyCode: String): Box[FXRate] = { + // Create request argument list + val req = OutboundCurrentFxRateBase( + messageFormat = messageFormat, + action = "obp.get.CurrentFxRate", + userId = currentResourceUserId, + username = AuthUser.getCurrentUserUsername, + fromCurrencyCode = fromCurrencyCode, + toCurrencyCode = toCurrencyCode) + + val r = { + cachedFxRate.getOrElseUpdate(req.toString, () => process(req).extract[InboundFXRate]) + } + // Return result + Full(new FXRate2(r)) + } + + messageDocs += MessageDoc( + process = "obp.get.TransactionRequestTypeCharge", + messageFormat = messageFormat, + description = "getTransactionRequestTypeCharge from kafka", + exampleOutboundMessage = Extraction.decompose( + OutboundTransactionRequestTypeChargeBase( + action = "obp.get.TransactionRequestTypeCharge", + messageFormat = messageFormat, + userId = "c7b6cb47-cb96-4441-8801-35b57456753a", + username = "susan.uk.29@example.com", + bankId = "gh.29.uk", + accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", + viewId = "owner", + transactionRequestType = "" + ) + ), + exampleInboundMessage = Extraction.decompose( + InboundTransactionRequestTypeCharge( + errorCode = "OBPS-001: .... ", + transactionRequestType = "", + bankId = "gh.29.uk", + chargeCurrency = "EUR", + chargeAmount = "2", + chargeSummary = " charge 1 eur" + ) + ) + ) + //get the current charge specified by bankId, accountId, viewId and transactionRequestType + override def getTransactionRequestTypeCharge( + bankId: BankId, + accountId: AccountId, + viewId: ViewId, + transactionRequestType: TransactionRequestType + ): Box[TransactionRequestTypeCharge] = { + + // Create request argument list + val req = OutboundTransactionRequestTypeChargeBase( + messageFormat = messageFormat, + action = "obp.get.TransactionRequestTypeCharge", + userId = currentResourceUserId, + username = AuthUser.getCurrentUserUsername, + bankId = bankId.value, + accountId = accountId.value, + viewId = viewId.value, + transactionRequestType = transactionRequestType.value + ) + + // send the request to kafka and get response + // TODO the error handling is not good enough, it should divide the error, empty and no-response. + val r = tryo {cachedTransactionRequestTypeCharge.getOrElseUpdate(req.toString, () => process(req).extract[InboundTransactionRequestTypeCharge])} + + // Return result + val result = r match { + case Full(f) => Full(TransactionRequestTypeCharge2(f)) + case _ => + for { + fromAccount <- getBankAccount(bankId, accountId) + fromAccountCurrency <- tryo{ fromAccount.currency } + } yield { + TransactionRequestTypeCharge2(InboundTransactionRequestTypeCharge( + + errorCode = "OBPS-001: .... ", + transactionRequestType.value, + bankId.value, + fromAccountCurrency, + "0.00", + "Warning! Default value!" + ) + ) + } + } + + result + } + + +//////////////////////////////Following is not over Kafka now ////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + + + override def getCounterparties(thisBankId: BankId, thisAccountId: AccountId,viewId :ViewId): Box[List[CounterpartyTrait]] = { + //note: kafka mode just used the mapper data + LocalMappedConnector.getCounterparties(thisBankId, thisAccountId, viewId) + } + override def getPhysicalCards(user: User): List[PhysicalCard] = + List() + + override def getPhysicalCardsForBank(bank: Bank, user: User): List[PhysicalCard] = + List() + + def AddPhysicalCard(bankCardNumber: String, + nameOnCard: String, + issueNumber: String, + serialNumber: String, + validFrom: Date, + expires: Date, + enabled: Boolean, + cancelled: Boolean, + onHotList: Boolean, + technology: String, + networks: List[String], + allows: List[String], + accountId: String, + bankId: String, + replacement: Option[CardReplacementInfo], + pinResets: List[PinResetInfo], + collected: Option[CardCollectionInfo], + posted: Option[CardPostedInfo] + ) : Box[PhysicalCard] = { + Empty + } + + + protected override def makePaymentImpl(fromAccount: BankAccount2, + toAccount: BankAccount2, + toCounterparty: CounterpartyTrait, + amt: BigDecimal, + description: String, + transactionRequestType: TransactionRequestType, + chargePolicy: String): Box[TransactionId] = { + + val sentTransactionId = saveTransaction(fromAccount, + toAccount, + toCounterparty, + amt, + description, + transactionRequestType, + chargePolicy) + + sentTransactionId + } + + override def createTransactionRequestImpl(transactionRequestId: TransactionRequestId, transactionRequestType: TransactionRequestType, account : BankAccount, counterparty : BankAccount, body: TransactionRequestBody, status: String, charge: TransactionRequestCharge) : Box[TransactionRequest] = { @@ -1578,125 +1721,27 @@ object KafkaMappedConnector_vMar2017 extends Connector with Loggable { override def getBranch(bankId : BankId, branchId: BranchId) : Box[MappedBranch]= Empty override def getConsumerByConsumerId(consumerId: Long): Box[Consumer] = Empty - - messageDocs += MessageDoc( - process = "obp.get.CurrentFxRate", - messageFormat = messageFormat, - description = "getCurrentFxRate from kafka", - exampleOutboundMessage = Extraction.decompose( - OutboundCurrentFxRate( - action = "obp.get.CurrentFxRate", - version = messageFormat, - userId = "c7b6cb47-cb96-4441-8801-35b57456753a", - username = "susan.uk.29@example.com", - fromCurrencyCode = "1234", - toCurrencyCode = "" - ) - ), - exampleInboundMessage = Extraction.decompose( - InboundFXRate( - fromCurrencyCode = "1234", - toCurrencyCode = "1234", - conversionValue = 123.44, - inverseConversionValue = 123.44, - effectiveDate = "" - ) - ), - errorResponseMessages = emptyObjectJson :: Nil - ) - // get the latest FXRate specified by fromCurrencyCode and toCurrencyCode. - override def getCurrentFxRate(fromCurrencyCode: String, toCurrencyCode: String): Box[FXRate] = { - // Create request argument list - val req = OutboundCurrentFxRate( - action = "obp.get.CurrentFxRate", - version = messageFormat, - userId = currentResourceUserId, - username = AuthUser.getCurrentUserUsername, - fromCurrencyCode = fromCurrencyCode, - toCurrencyCode = toCurrencyCode) - - val r = { - cachedFxRate.getOrElseUpdate(req.toString, () => process(req).extract[InboundFXRate]) - } - // Return result - Full(new FXRate2(r)) - } - - messageDocs += MessageDoc( - process = "obp.get.TransactionRequestTypeCharge", - messageFormat = messageFormat, - description = "getTransactionRequestTypeCharge from kafka", - exampleOutboundMessage = Extraction.decompose( - OutboundTransactionRequestTypeCharge( - action = "obp.get.TransactionRequestTypeCharge", - version = messageFormat, - userId = "c7b6cb47-cb96-4441-8801-35b57456753a", - username = "susan.uk.29@example.com", - bankId = "gh.29.uk", - accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", - viewId = "owner", - transactionRequestType = "" - ) - ), - exampleInboundMessage = Extraction.decompose( - InboundTransactionRequestTypeCharge( - transactionRequestType = "", - bankId = "gh.29.uk", - chargeCurrency = "EUR", - chargeAmount = "2", - chargeSummary = " charge 1 eur" - ) - ), - errorResponseMessages = emptyObjectJson :: Nil - ) - //get the current charge specified by bankId, accountId, viewId and transactionRequestType - override def getTransactionRequestTypeCharge(bankId: BankId, accountId: AccountId, viewId: ViewId, transactionRequestType: TransactionRequestType): Box[TransactionRequestTypeCharge] = { - - // Create request argument list - val req = OutboundTransactionRequestTypeCharge( - action = "obp.get.TransactionRequestTypeCharge", - version = messageFormat, - userId = currentResourceUserId, - username = AuthUser.getCurrentUserUsername, - bankId = bankId.value, - accountId = accountId.value, - viewId = viewId.value, - transactionRequestType = transactionRequestType.value) - - // send the request to kafka and get response - // TODO the error handling is not good enough, it should divide the error, empty and no-response. - val r = tryo { - cachedTransactionRequestTypeCharge.getOrElseUpdate(req.toString, () => process(req).extract[InboundTransactionRequestTypeCharge]) - } - - // Return result - val result = r match { - case Full(f) => Full(TransactionRequestTypeCharge2(f)) - case _ => - for { - fromAccount <- getBankAccount(bankId, accountId) - fromAccountCurrency <- tryo{ fromAccount.currency } - } yield { - TransactionRequestTypeCharge2(InboundTransactionRequestTypeCharge(transactionRequestType.value, bankId.value, fromAccountCurrency, "0.00", "Warning! Default value!")) - } - } - - result - } - + + override def getEmptyBankAccount(): Box[AccountType] = { - Full(new BankAccount2(InboundAccount(accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", - bankId = "gh.29.uk", - label = "Good", - number = "123", - `type` = "AC", - balanceAmount = "50", - balanceCurrency = "EUR", - iban = "12345", - owners = Nil, - generatePublicView = true, - generateAccountantsView = true, - generateAuditorsView = true))) + Full(new BankAccount2( + InboundAccount( + errorCode = "OBPS-001: .... ", + accountId = "8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0", + bankId = "gh.29.uk", + label = "Good", + number = "123", + `type` = "AC", + balanceAmount = "50", + balanceCurrency = "EUR", + iban = "12345", + owners = Nil, + generatePublicView = true, + generateAccountantsView = true, + generateAuditorsView = true + ) + ) + ) } /////////////////////////////////////////////////////////////////////////////