From 403d79c03e669f37d72ddf2cb554725e3044869e Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 7 Oct 2022 13:28:40 +0200 Subject: [PATCH] feature/OBPV500 CustomerAccountLink endpoints - step1: added CustomerAccountLink mode --- .../main/scala/bootstrap/liftweb/Boot.scala | 4 +- .../scala/code/api/util/ErrorMessages.scala | 1 + .../CustomerAccountLink.scala | 54 +++++++++++ .../MappedCustomerAccountLink.scala | 93 +++++++++++++++++++ .../RemotedataCustomerAccountLinks.scala | 48 ++++++++++ .../RemotedataCustomerAccountLinksActor.scala | 58 ++++++++++++ 6 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 obp-api/src/main/scala/code/customeraccountlinks/CustomerAccountLink.scala create mode 100644 obp-api/src/main/scala/code/customeraccountlinks/MappedCustomerAccountLink.scala create mode 100644 obp-api/src/main/scala/code/remotedata/RemotedataCustomerAccountLinks.scala create mode 100644 obp-api/src/main/scala/code/remotedata/RemotedataCustomerAccountLinksActor.scala diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 4a92d6364..a60ab2f36 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -102,6 +102,7 @@ import code.apicollectionendpoint.ApiCollectionEndpoint import code.apicollection.ApiCollection import code.bankattribute.BankAttribute import code.connectormethod.ConnectorMethod +import code.customeraccountlinks.CustomerAccountLink import code.dynamicMessageDoc.DynamicMessageDoc import code.dynamicResourceDoc.DynamicResourceDoc import code.endpointMapping.EndpointMapping @@ -967,7 +968,8 @@ object ToSchemify { BankAttribute, RateLimiting, MappedCustomerDependant, - AttributeDefinition + AttributeDefinition, + CustomerAccountLink ) // The following tables are accessed directly via Mapper / JDBC diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 7eb89e727..6736ad631 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -401,6 +401,7 @@ object ErrorMessages { val InvalidCardNumber = "OBP-30200: Card not found. Please specify a valid value for CARD_NUMBER. " + val CustomerAccountLinkNotFound = "OBP-30204:Customer Account Link not found" val EntitlementIsBankRole = "OBP-30205: This entitlement is a Bank Role. Please set bank_id to a valid bank id." val EntitlementIsSystemRole = "OBP-30206: This entitlement is a System Role. Please set bank_id to empty string." diff --git a/obp-api/src/main/scala/code/customeraccountlinks/CustomerAccountLink.scala b/obp-api/src/main/scala/code/customeraccountlinks/CustomerAccountLink.scala new file mode 100644 index 000000000..96a75ac10 --- /dev/null +++ b/obp-api/src/main/scala/code/customeraccountlinks/CustomerAccountLink.scala @@ -0,0 +1,54 @@ +package code.customeraccountlinks + +import code.api.util.APIUtil +import code.remotedata.RemotedataCustomerAccountLinks +import net.liftweb.common.Box +import net.liftweb.util.SimpleInjector + +import scala.concurrent.Future + + +object CustomerAccountLinkTrait extends SimpleInjector { + + val customerAccountLink = new Inject(buildOne _) {} + + def buildOne: CustomerAccountLinkProvider = + APIUtil.getPropsAsBoolValue("use_akka", false) match { + case false => MappedCustomerAccountLinkProvider + case true => RemotedataCustomerAccountLinks // We will use Akka as a middleware + } + +} + +trait CustomerAccountLinkProvider { + def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String): Box[CustomerAccountLinkTrait] + def getOCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType: String): Box[CustomerAccountLinkTrait] + def getCustomerAccountLinkByCustomerId(customerId: String): Box[CustomerAccountLinkTrait] + def getCustomerAccountLinksByCustomerId(customerId: String): List[CustomerAccountLinkTrait] + def getCustomerAccountLinksByAccountId(accountId: String): List[CustomerAccountLinkTrait] + def getCustomerAccountLink(customerId: String, accountId: String): Box[CustomerAccountLinkTrait] + def getCustomerAccountLinks: Box[List[CustomerAccountLinkTrait]] + def bulkDeleteCustomerAccountLinks(): Boolean + def deleteCustomerAccountLink(customerAccountLinkId: String): Future[Box[Boolean]] +} + +class RemotedataCustomerAccountLinkProviderCaseClass { + case class createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String) + case class getOCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType: String) + case class getCustomerAccountLinkByCustomerId(customerId: String) + case class getCustomerAccountLinksByCustomerId(customerId: String) + case class getCustomerAccountLinksByAccountId(accountId: String) + case class getCustomerAccountLink(customerId: String, accountId: String) + case class getCustomerAccountLinks() + case class bulkDeleteCustomerAccountLinks() + case class deleteCustomerAccountLink(customerAccountLinkId: String) +} + +object RemotedataCustomerAccountLinkProviderCaseClass extends RemotedataCustomerAccountLinkProviderCaseClass + +trait CustomerAccountLinkTrait { + def customerAccountLinkId: String + def customerId: String + def accountId: String + def relationshipType: String +} \ No newline at end of file diff --git a/obp-api/src/main/scala/code/customeraccountlinks/MappedCustomerAccountLink.scala b/obp-api/src/main/scala/code/customeraccountlinks/MappedCustomerAccountLink.scala new file mode 100644 index 000000000..fe5ad0f6f --- /dev/null +++ b/obp-api/src/main/scala/code/customeraccountlinks/MappedCustomerAccountLink.scala @@ -0,0 +1,93 @@ +package code.customeraccountlinks + +import code.api.util.ErrorMessages +import code.util.{MappedUUID, UUIDString} +import net.liftweb.common.{Box, Empty, Failure, Full} +import net.liftweb.mapper._ + +import scala.concurrent.Future +import com.openbankproject.commons.ExecutionContext.Implicits.global + +object MappedCustomerAccountLinkProvider extends CustomerAccountLinkProvider { + def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String): Box[CustomerAccountLinkTrait] = { + + val createCustomerAccountLink = CustomerAccountLink.create + .CustomerId(customerId) + .AccountId(accountId) + .RelationshipType(relationshipType) + .saveMe() + + Some(createCustomerAccountLink) + } + def getOCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType: String): Box[CustomerAccountLinkTrait] = { + getCustomerAccountLink(accountId, customerId) match { + case Empty => + val createCustomerAccountLink = CustomerAccountLink.create + .CustomerId(customerId) + .AccountId(accountId) + .RelationshipType(relationshipType) + .saveMe() + Some(createCustomerAccountLink) + case everythingElse => everythingElse + } + } + + def getCustomerAccountLinkByCustomerId(customerId: String): Box[CustomerAccountLinkTrait] = { + CustomerAccountLink.find( + By(CustomerAccountLink.CustomerId, customerId)) + } + def getCustomerAccountLinksByCustomerId(customerId: String): List[CustomerAccountLinkTrait] = { + CustomerAccountLink.findAll( + By(CustomerAccountLink.CustomerId, customerId)) + } + + def getCustomerAccountLinksByAccountId(accountId: String): List[CustomerAccountLinkTrait] = { + val customerAccountLinks : List[CustomerAccountLinkTrait] = CustomerAccountLink.findAll( + By(CustomerAccountLink.AccountId, accountId)).sortWith(_.id.get < _.id.get) + customerAccountLinks + } + + def getCustomerAccountLink(accountId : String, customerId: String): Box[CustomerAccountLinkTrait] = { + CustomerAccountLink.find( + By(CustomerAccountLink.AccountId, accountId), + By(CustomerAccountLink.CustomerId, customerId)) + } + + def getCustomerAccountLinks: Box[List[CustomerAccountLinkTrait]] = { + Full(CustomerAccountLink.findAll()) + } + + def bulkDeleteCustomerAccountLinks(): Boolean = { + CustomerAccountLink.bulkDelete_!!() + } + + def deleteCustomerAccountLink(customerAccountLinkId: String): Future[Box[Boolean]] = { + Future { + CustomerAccountLink.find(By(CustomerAccountLink.CustomerAccountLinkId, customerAccountLinkId)) match { + case Full(t) => Full(t.delete_!) + case Empty => Empty ?~! ErrorMessages.CustomerAccountLinkNotFound + case Failure(msg, exception, chain) => Failure(msg, exception, chain) + } + } + } +} + +class CustomerAccountLink extends CustomerAccountLinkTrait with LongKeyedMapper[CustomerAccountLink] with IdPK with CreatedUpdated { + + def getSingleton = CustomerAccountLink + + object CustomerAccountLinkId extends MappedUUID(this) + object CustomerId extends UUIDString(this) + object AccountId extends UUIDString(this) + object RelationshipType extends MappedString(this, 255) + + override def customerAccountLinkId: String = CustomerAccountLinkId.get + override def customerId: String = CustomerId.get // id.toString + override def accountId: String = AccountId.get + override def relationshipType: String = RelationshipType.get +} + +object CustomerAccountLink extends CustomerAccountLink with LongKeyedMetaMapper[CustomerAccountLink] { + override def dbIndexes = UniqueIndex(CustomerAccountLinkId) :: UniqueIndex(AccountId, CustomerId) :: super.dbIndexes + +} diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataCustomerAccountLinks.scala b/obp-api/src/main/scala/code/remotedata/RemotedataCustomerAccountLinks.scala new file mode 100644 index 000000000..d41457f72 --- /dev/null +++ b/obp-api/src/main/scala/code/remotedata/RemotedataCustomerAccountLinks.scala @@ -0,0 +1,48 @@ +package code.remotedata + +import akka.pattern.ask +import code.actorsystem.ObpActorInit +import code.customeraccountlinks.{RemotedataCustomerAccountLinkProviderCaseClass, CustomerAccountLinkTrait, CustomerAccountLinkProvider} +import net.liftweb.common._ +import scala.concurrent.Future + + +object RemotedataCustomerAccountLinks extends ObpActorInit with CustomerAccountLinkProvider { + + val cc = RemotedataCustomerAccountLinkProviderCaseClass + + def createCustomerAccountLink(customerId: String, accountId: String, relationshipType: String) : Box[CustomerAccountLinkTrait] = getValueFromFuture( + (actor ? cc.createCustomerAccountLink(accountId, customerId, relationshipType)).mapTo[Box[CustomerAccountLinkTrait]] + ) + + def getOCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType: String) : Box[CustomerAccountLinkTrait] = getValueFromFuture( + (actor ? cc.getOCreateCustomerAccountLink(accountId, customerId, relationshipType)).mapTo[Box[CustomerAccountLinkTrait]] + ) + + def getCustomerAccountLinkByCustomerId(customerId: String): Box[CustomerAccountLinkTrait] = getValueFromFuture( + (actor ? cc.getCustomerAccountLinkByCustomerId(customerId)).mapTo[Box[CustomerAccountLinkTrait]] + ) + def getCustomerAccountLinksByCustomerId(customerId: String): List[CustomerAccountLinkTrait] = getValueFromFuture( + (actor ? cc.getCustomerAccountLinksByCustomerId(customerId)).mapTo[List[CustomerAccountLinkTrait]] + ) + + def getCustomerAccountLinksByAccountId(accountId: String): List[CustomerAccountLinkTrait] = getValueFromFuture( + (actor ? cc.getCustomerAccountLinksByAccountId(accountId)).mapTo[List[CustomerAccountLinkTrait]] + ) + + def getCustomerAccountLink(customerId: String, accountId: String): Box[CustomerAccountLinkTrait] = getValueFromFuture( + (actor ? cc.getCustomerAccountLink(accountId, customerId)).mapTo[Box[CustomerAccountLinkTrait]] + ) + + def getCustomerAccountLinks: Box[List[CustomerAccountLinkTrait]] = getValueFromFuture( + (actor ? cc.getCustomerAccountLinks()).mapTo[Box[List[CustomerAccountLinkTrait]]] + ) + + def bulkDeleteCustomerAccountLinks(): Boolean = getValueFromFuture( + (actor ? cc.bulkDeleteCustomerAccountLinks()).mapTo[Boolean] + ) + def deleteCustomerAccountLink(customerAccountLinkId: String): Future[Box[Boolean]] = + (actor ? cc.deleteCustomerAccountLink(customerAccountLinkId)).mapTo[Box[Boolean]] + + +} diff --git a/obp-api/src/main/scala/code/remotedata/RemotedataCustomerAccountLinksActor.scala b/obp-api/src/main/scala/code/remotedata/RemotedataCustomerAccountLinksActor.scala new file mode 100644 index 000000000..ba4fc9a9d --- /dev/null +++ b/obp-api/src/main/scala/code/remotedata/RemotedataCustomerAccountLinksActor.scala @@ -0,0 +1,58 @@ +package code.remotedata + +import akka.actor.Actor +import akka.pattern.pipe +import code.actorsystem.ObpActorHelper +import code.customeraccountlinks.{MappedCustomerAccountLinkProvider, RemotedataCustomerAccountLinkProviderCaseClass} +import code.util.Helper.MdcLoggable +import com.openbankproject.commons.ExecutionContext.Implicits.global + +class RemotedataCustomerAccountLinksActor extends Actor with ObpActorHelper with MdcLoggable { + + val mapper = MappedCustomerAccountLinkProvider + val cc = RemotedataCustomerAccountLinkProviderCaseClass + + def receive: PartialFunction[Any, Unit] = { + + case cc.createCustomerAccountLink(customerId: String, accountId: String, relationshipType) => + logger.debug(s"createCustomerAccountLink($accountId, $relationshipType)") + sender ! (mapper.createCustomerAccountLink(accountId, customerId, relationshipType)) + + case cc.getOCreateCustomerAccountLink(customerId: String, accountId: String, relationshipType) => + logger.debug(s"getOCreateCustomerAccountLink($accountId, $relationshipType)") + sender ! (mapper.getOCreateCustomerAccountLink(accountId, customerId, relationshipType)) + + case cc.getCustomerAccountLinkByCustomerId(customerId: String) => + logger.debug(s"getCustomerAccountLinkByCustomerId($customerId)") + sender ! (mapper.getCustomerAccountLinkByCustomerId(customerId)) + + case cc.getCustomerAccountLinksByCustomerId(customerId: String) => + logger.debug(s"getCustomerAccountLinksByCustomerId($customerId)") + sender ! (mapper.getCustomerAccountLinksByCustomerId(customerId)) + + case cc.getCustomerAccountLinksByAccountId(accountId: String) => + logger.debug(s"getCustomerAccountLinksByAccountId($accountId)") + sender ! (mapper.getCustomerAccountLinksByAccountId(accountId)) + + case cc.getCustomerAccountLink(customerId: String, accountId: String) => + logger.debug(s"getCustomerAccountLink($accountId, $customerId)") + sender ! (mapper.getCustomerAccountLink(accountId, customerId)) + + case cc.getCustomerAccountLinks() => + logger.debug(s"getCustomerAccountLinks()") + sender ! (mapper.getCustomerAccountLinks) + + case cc.bulkDeleteCustomerAccountLinks() => + logger.debug(s"bulkDeleteCustomerAccountLinks()") + sender ! (mapper.bulkDeleteCustomerAccountLinks()) + + case cc.deleteCustomerAccountLink(customerAccountLinkId) => + logger.debug(s"deleteCustomerAccountLink($customerAccountLinkId)") + mapper.deleteCustomerAccountLink(customerAccountLinkId) pipeTo sender + + case message => logger.warn("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message) + + } + +} +